Large images - speed issues SOLVED

Game development specific discussions.
Post Reply
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Large images - speed issues SOLVED

Post by datwill310 »

In my game loop, graphics are constantly being erased, redrawn, and drawn onto the screen. I have commented out certain parts of this graphical part of my game and it does not influence speed of the game (admittedly there are only a dozen or so things on the screen and no moving things at this point).
I'm not 100% sure, but it seems that working with images larger than a few thousand pixels in width (the currently used image is 3072*618 which displays the stage you are playing on) presents various speed problems with my FB program, particularly in the realms of drawing such an image to screen.
I understand the speed problems if I simply draw the entire image, only showing a segment of it due to the size of the graphics window. There are TONS of pixels to deal with, and that number will ONLY get bigger as the stages become much larger (possibly into the tens of thousands of pixels wide).
This is what I was doing originally. I noticed this, and instead now I only draw a select portion of that image (1024*618), which in theory shouldn't make the game too slow as when I was working with this stage size before, there were almost no speed deficiencies. Well, I was wrong. Absolutely NO speed was gained in doing so. I would have thought it would, because isn't selecting a portion of the image using (x, y)-(x, y) in the put command directly accessing said pixels, as if they were simply a memory location?
So it seems even remotely dealing with a very large image in a loop causes an FB program to slow down so drastically?
I have this question;
In what way can I make my FreeBASIC program run faster if I am working with such large images?
The large image I was referring to is dealt with only internally and does not save and load from an image file. I am currently using this:

Code: Select all

put (0, 0), graphic, (bg_x_offset, 0)-(bg_x_offset+1024, 618), pset
To draw my graphic to the screen, where bg_x_offset is a variable used for the scrolling engine to move the background along (i.e. select the 1024*618 portion of my stage graphic to display). I have commented out various parts of graphical updating and that hardly if at all influences speed at the moment. What does influence speed is that line, I am mostly sure. This tells me that: blitting an image onto another image is pretty damn fast, and blitting an image to the screen is comparatively slow. I'm pretty sure this was to do with how memory was managed for the screen?
I would post some code but I'm trying to keep it pretty closed-sourced right now. I will provide any details about my code you would like.
Last edited by datwill310 on May 25, 2017 16:17, edited 1 time in total.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Large images - speed issues

Post by dafhi »

haven't played with this in a while, but i made a blit sub

Code: Select all

sub imagevars.maskblit(x as integer, y as integer, mask_col as ulong)', byref pdest as imagevars ptr)
  dim as ulong ptr _src = pixels, _dst = pdest->pixels
  _dst -= x*(x>0) + pdest->pitchBy*y*(y>0)  '' pitchBy = pitch \ bypp
  _src += x*(x<0) + pitchBy*y*(y<0)
  
  '' wm = w - 1
  '' hm = h - 1
  x = (x+wm-pdest->wm)*((x+wm)>pdest->wm)+wm-x*(x<0) ' x and y repurposed to clipped width and height
  y = (y+hm-pdest->hm)*((y+hm)>pdest->hm)+hm-y*(y<0)
  for yy as ulong ptr = _dst to @_dst[(y)*pdest->pitchBy] step pdest->pitchBy  '' pitchBy = pitch \ bypp
    dim as ulong ptr src = _src
    for xx as ulong ptr = yy to @yy[x]
      if *src<>mask_col then *xx = *src
      src+=1
    next
    _src += pitchBy
  next
end sub
Last edited by dafhi on May 25, 2017 12:38, edited 1 time in total.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Large images - speed issues

Post by MrSwiss »

Well, I'd use a *intermediate* image (sized equally as "ScreenRes"), also
*double buffering*, similar to below:

Code: Select all

' 2017-05-25, by MrSWiss
ScreenRes(1024, 768, 32, 2)
ScreenSet(1, 0)

Dim As Any Ptr  bg_img = ImageCreate(3200, 1800, &hFF007FFF, 32)    ' all bg
Line bg_img, (50, 25)-Step(99,49), &hFFCFCF00, BF   ' proof of concept only

Dim As Any Ptr  buffer = ImageCreate(1024,  768,, 32)   ' screen portion bg
Dim As Long     x_offs = 100, y_offs = 50

Do
    Get bg_img, (x_offs, y_offs)-step(1023, 767), buffer
    Put (0, 0), buffer, Trans 
    Flip
    Sleep 10, 1
Loop Until Len(InKey)
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Large images - speed issues

Post by datwill310 »

Thanks guys and will experiment!

EDIT: :/ hmm, speed is not improving. This is making me think something else is wrong...
When I use a 1024 wide stage graphic, speed is pretty fast, jumping straight up and landing on the same platform takes approx. 0.95 seconds.
When I use a 3072 wide stage graphic, speed is comparatively slow, jumping straight up and landing on the same surface takes approx. 1.46 seconds.
When I use a 10000 wide stage graphic, speed is God-awfully slow, jumping in the same way takes approx. 2.51 seconds.
Stages will be larger than 10000 pixels wide.
This is all using a temporary double-buffering system.
Is there something wrong with the way I'm doing it?

Code: Select all

'extract
h_updateGraphic
h_updateHud
screenlock
	cls 'this is required for some text to work in this loop. There are only four lines and commenting them out doesn't do anything to speed
	put (0, 618), hud, pset 'the HUD
	put (0, 0), graphic, (bg_x_offset, 0)-(bg_x_offset+1024, 618), pset 'the stage graphic
screenunlock
pcopy 1, 0 'copy from working page 1 to visible page 0
Last edited by datwill310 on May 25, 2017 13:23, edited 1 time in total.
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Large images - speed issues

Post by BasicCoder2 »

The size of the stored image shouldn't affect the speed of the put statement used as you say you do.
Do you mean it scrolls slow?
Do you scroll it with the keyboard?
Try this and see how fast it moves.
I saved 4608x3456 image as bigPic.bmp
While the mouse button is held down you can move the image around with the mouse.

Code: Select all

screenres 1024,618,32
color rgb(0,0,0),rgb(255,255,255)
cls

Const NULL As Any Ptr = 0
type PICTURE
    as integer x
    as integer y
    as integer w
    as integer h
    as uinteger fg
    as uinteger bg
    as any ptr i   'image
end type

dim shared as PICTURE Pic

Pic.x = 5
Pic.y = 5
Pic.w = 1024
pic.h = 618
pic.i = NULL


dim shared as integer iWidth,iHeight     'width and height of pic.i

sub loadImage(file as string)
    if pic.i <> NULL then
        imageDestroy(pic.i)  'release memory
    end if
    dim as integer fileHnd = FreeFile()
    'get width and height of bitmap
    open file for binary as #fileHnd
    get #fileHnd, 19, iWidth
    get #fileHnd, 23, iHeight
    close #fileHnd
    'initialize pointers to pic.i bitmaps
    pic.i = imagecreate(iWidth,iHeight,rgb(255,255,255))
    bload file,pic.i  'bload bitmap pic.i
    If pic.i = NULL Then
        Print "image creation failed!"
        Sleep
        End
    End If
end sub


dim shared as double offx,offy,dx,dy
dim shared as integer mx,my,mw,mb,ox,oy,ow,ob

offx = 0
offy = 0

sub drawPictureBox()
    
    put (pic.x,pic.y),pic.i,(offx,offy)-(offx+pic.w-1,offy+pic.h-1),pset  'picture

    
    line (pic.x,pic.y)-(pic.x+pic.w-1,pic.y+pic.h-1),rgb(0,0,0),b         'picture border
    
    
end sub

sub update()
    screenlock()
    cls
    drawPictureBox()

    screenunlock()
    sleep 2
end sub

'=========================================================================
'  START OF PROGRAM
'=========================================================================
loadImage("bigPic.bmp")            'file name of a very large image

getmouse mx,my,mb  '

do
    getmouse mx,my,,mb
    
    if mb = 1 then
        
        ox = mx
        oy = my

        while mb = 1
            getmouse mx,my,,mb
            if mx<>ox or my<>oy then  'mouse moved
                offx = offx + (ox-mx)
                offy = offy + (oy-my)
                if offx <0 then offx = 0
                if offy <0 then offy = 0
                if offx >= iWidth - pic.w then
                    offx = iWidth - pic.w
                end if
                if offy >= iHeight - pic.h then
                    offy = iHeight -pic.h
                end if
                ox = mx
                oy = my
                update()
            end if
            sleep 2
        wend

    end if
    
    update()
    sleep 2
loop until multikey(&H01)

if pic.i <> NULL then
    imageDestroy(pic.i)  'release memory
end if
    
sleep

datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Large images - speed issues

Post by datwill310 »

BasicCoder2 wrote:The size of the stored image shouldn't affect the speed of the put statement used as you say you do.
Do you mean it scrolls slow?
Do you scroll it with the keyboard?
Try this and see how fast it moves.
1. Scrolling is affected by this, but I really notice the speed difference with moving my main character. He scrolls the stage graphic by moving, if this is what you mean. I have edited my above post giving some rough benchmarks with jumping in the exact same way under each size I've tried properly so far.
2. You can control the main character with either the keyboard or a gamepad. I have not tested if using a gamepad makes it faster though.
3. I will try: who knows, maybe it's just my potato of a system xD!

EDIT: I have run the test you provided. As far as speed goes, the program is very responsive as I move it around with the mouse.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Large images - speed issues

Post by datwill310 »

UPDATE! I have found the issue.

It was not with drawing the stage graphic. It was to do with drawing the background. Just tried playing without drawing the background with large image and everything runs smoothly!

I use this statement to draw the background onto the graphic:

Code: Select all

put graphic, (0, 0), background, pset
A general note: the background image is the same size as the graphic image. The background is a 1024 by 608 image tiled in the x direction. If we can't find a solution to this I could just draw that single image and be done with it, but it isn't as nice as a scrolling background/it looks more realistic. Tiling graphics is slow, so that is done upon stage loading and not in the game loop.
Oh great, it boils down to the same issue really :/
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Large images - speed issues

Post by MrSwiss »

Another Tip: reduce Color to 8bit (aka: palette), to gain more speed ...
(reduction of IMG size to 1/4, compared to 32bit Color)

Most every improvement comes at a price ...
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Large images - speed issues

Post by datwill310 »

MrSwiss wrote:Another Tip: reduce Color to 8bit (aka: palette), to gain more speed ...
(reduction of IMG size to 1/4, compared to 32bit Color)

Most every improvement comes at a price ...
You're right about the speed improvement o_O,
however, the costs are too high for me to take this route:
1. 8-bit does not have the alpha channel (?), so everything now looks like a rectangle.
2. Colours used in the current 32-bit images are varied and we may end up using a palette beyond 256 values.
3. Not to mention we will have to redraw everything.
4. Libraries I use with my game look not too good either when used with 8-bit.
5. I think some stuff just vanished altogether.

However, I am considering now using a static background:
- Reduces amount of pixels to draw.
- We can keep our colours.
- And alpha.
- While not looking too bad, though not the best, it is probably suitable.

I would like to thank you for the suggestion, though.

EDIT: problem solved: turns out all I needed to do was only draw a portion of the background and not all of it!
Post Reply