Faster vector graphics

Just starting out? Need help? Post your questions and find answers here.
coco2
Enthusiast
Enthusiast
Posts: 461
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Faster vector graphics

Post by coco2 »

Is it possible to get faster vector graphics? I want to use them in my game running 60 FPS or above and the built in ones are not fast enough. Also I looked into making my own library using DrawingBuffer() but that is also not fast enough since it needs "StartDrawing(ScreenOutput()) which takes 5ms. I don't actually know what the purpose of it is, if you are directly drawing to the screen then you need it to be fast, and if you are not making realtime graphics then there's no need to draw directly to the screen, so it seems pointless to me.

Can 3rd party libraries give faster graphics in PureBasic?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Faster vector graphics

Post by netmaestro »

The Sprite library will give you the fastest performance.
BERESHEIT
coco2
Enthusiast
Enthusiast
Posts: 461
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Faster vector graphics

Post by coco2 »

I've been using the sprite library, and I've been drawing vector graphics to sprites, then drawing the sprites but the anti-aliasing isn't as good as when you draw directly with the vector commands, especially when rotating sprites.
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: Faster vector graphics

Post by pjay »

Can you post some demo code that demonstrates what you're trying to achieve but is too slow for your needs?
#NULL
Addict
Addict
Posts: 1498
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Faster vector graphics

Post by #NULL »

You can speed up some things by using threads. What I did in a project is this (was vectordrawing on a canvas for a game):
- when you get the data for drawing, don't draw it directly, but instead collect it in a structured list. For example coordinates, thickness ect. of lines/shapes you want to draw.
- in a separate thread, you use this data (or better a copy of it) to draw it on an image.
- while that other thread is drawing the new frame (image), your main thread can display the previously drawn image (swap images, don't recreate of course) in a canvas and can do the other game logic as well as collecting the new data for the new frame.
- these two parallel parts are supposed to overlap, but not outtake each other. So you need to coordinate with semaphores on both sides signaling each other to ensure a strictly alternating order.
coco2
Enthusiast
Enthusiast
Posts: 461
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Faster vector graphics

Post by coco2 »

pjay wrote: Sat Dec 02, 2023 9:27 am Can you post some demo code that demonstrates what you're trying to achieve but is too slow for your needs?
I will get back to you. I really believe that all the graphics capabilities in PureBasic cannot be used for games except for sprites.
#NULL wrote: Sat Dec 02, 2023 10:04 am You can speed up some things by using threads.
I tested that out recently and concluded that drawing images was too slow. What frame time did you have? With a 60 hz monitor it is 16 ms, but with a 240hz monitor it's 4 ms. StartDrawing can take up to 1 ms, DrawAlphaImage up to 1 ms and StopDrawing up to 1 ms, that's potentially 3 ms just to draw one image. A modern PC should be able to draw 2D graphics easily at 240 hz.
#NULL
Addict
Addict
Posts: 1498
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Faster vector graphics

Post by #NULL »

I wasn't drawing the image myself, I only used SetGadgetAttribute(canvas, #PB_Canvas_Image, ImageID(img)). Not sure what blitting or copying PB does internally.

I looked into my notes of the project and it says that the initial version with those changes wasn't actually faster but a bit slower, so I'm not sure anymore if I gained some speed with additional later optimizations or not. :oops: . My FPS still sucked, but I had a lot of drawing and I have poor hardware, so I guess you would have to see for yourself if it could help in your situation.
User avatar
mk-soft
Always Here
Always Here
Posts: 6237
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Faster vector graphics

Post by mk-soft »

Refreshing the images over 60 frames makes no sense, as the brain is slower anyway. Actually, 30 frames is enough for the eye to have a smooth picture. The 4 ms (240 HZ) are only good to prevent the monitor's pixels from glowing.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: Faster vector graphics

Post by pjay »

mk-soft wrote: Sat Dec 02, 2023 2:26 pm Refreshing the images over 60 frames makes no sense...
I respectfully disagree; whilst I agree that 30fps is the generally the minimum needed, my laptop can switch between 60fps and 120fps & the difference in smoothness between the two is still very noticable.

@coco2
I'll always lean towards hardware accelerated options when it comes to realtime graphics applications.

If the sprite library doesn't fulfill your requirements then I'd write some OpenGL code that does the job, abstract it if necessary to make your life easier. I'd imagine even the legacy immediate mode that PB supports natively would be more than sufficient and capable of 100s of frames per second on most modern PCs.
User avatar
mk-soft
Always Here
Always Here
Posts: 6237
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Faster vector graphics

Post by mk-soft »

A CanvasGadget is too slow and too calculation intensive.

Example with 30 frames

Code: Select all

;-TOP

#ProgramTitle = "Main Window"
#ProgramVersion = "v1.01.2"

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  #MainCanvas
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

UsePNGImageDecoder()
UseJPEGImageDecoder()

Global image1, image2

Procedure LoadResources()
  image1 = LoadImage(0, #PB_Compiler_Home + "examples/3d/Data/Textures/flare.png")
  image2 = LoadImage(1, #PB_Compiler_Home + "examples/3d/Data/Textures/Lensflare5.jpg")
EndProcedure

Procedure Limit(*Value.integer, Min, Max)
  If *Value\i < Min
    *Value\i = Min
  ElseIf *Value\i >= Max
    *Value\i = Max
  EndIf
EndProcedure

Procedure FilterCallback(x, y, SourceColor, TargetColor)
  If SourceColor > TargetColor 
    ProcedureReturn SourceColor
  Else
    ProcedureReturn TargetColor
  EndIf
EndProcedure

Procedure RedrawGadget(Gadget)
  Static x1, y1, x2, y2, xdir1 = 5, ydir1 = 5, xdir2 = 5, ydir2 = 5
  Protected dx, dy
  
  dx = GadgetWidth(Gadget)
  dy = GadgetHeight(Gadget)
  
  If StartDrawing(CanvasOutput(Gadget))
    If x1 < -100
      xdir1 = Random(20,5)
    ElseIf x1 > dx - 50
      xdir1 = Random(20,5) * -1
    EndIf
    If y1 < -100
      ydir1 = Random(20,5)
    ElseIf y1 > dy - 50
      ydir1 = Random(20,5) * -1
    EndIf
    
    If x2 < -100
      xdir2 = Random(20,5)
    ElseIf x2 > dx - 50
      xdir2 = Random(20,5) * -1
    EndIf
    If y2 < -100
      ydir2 = Random(20,5)
    ElseIf y2 > dy - 50
      ydir2 = Random(20,5) * -1
    EndIf
    
    x1 + xdir1
    y1 + ydir1
    
    x2 + xdir2
    y2 + ydir2
    
    Box(0, 0, dx, dy, 0)
    DrawingMode(#PB_2DDrawing_CustomFilter)      
    CustomFilterCallback(@FilterCallback())
    DrawImage(image2, x2, y2)
    DrawImage(image1, x1, y1)
    StopDrawing()
    
  EndIf
  
EndProcedure

Procedure DoEventTimer()
  RedrawGadget(0)
EndProcedure

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
  ; Resize gadgets
  ResizeGadget(#MainCanvas, 0, 0, dx, dy)
  
EndProcedure

Procedure Main()
  Protected dx, dy, time, lasttime
  
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
    ; Menu
    CreateMenu(#MainMenu, WindowID(#Main))
    MenuTitle("&File")
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      MenuItem(#PB_Menu_About, "")
    CompilerElse
      MenuItem(#MainMenuAbout, "About")
    CompilerEndIf
    ; Menu File Items
    
    CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
      MenuBar()
      MenuItem(#MainMenuExit, "E&xit")
    CompilerEndIf
    
    ; StatusBar
    CreateStatusBar(#MainStatusBar, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    CanvasGadget(0, 0, 0, dx, dy, #PB_Canvas_Border)
    
    LoadResources()
    
    RedrawGadget(#MainCanvas)
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
    BindEvent(#PB_Event_Timer, @DoEventTimer(), 0, 1)
    
    ;AddWindowTimer(0, 1, 33)
    
    lasttime = ElapsedMilliseconds()
    ; Event Loop
    Repeat
      Select WaitWindowEvent(1)
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              Break
              
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            CompilerEndIf
            
          Case #MainMenuAbout
            MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
              
          Case #MainMenuExit
            PostEvent(#PB_Event_CloseWindow, #Main, #Null)
            
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
              
          EndSelect
          
      EndSelect
      
      time = ElapsedMilliseconds()
      If time - lasttime >= 33
        RedrawGadget(#MainCanvas)
        lasttime = time
      EndIf
      
    ForEver
    
  EndIf
  
EndProcedure : Main()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 18175
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Faster vector graphics

Post by Fred »

When using the sprite lib, you should precalculate everything before launching your rendering loop and never use startdrawing() in it. ScreenOutput() is basically only useful for debugging because it's very slow (you need to transfer GFX mem to main mem and then back, it's very costly).

That's why shaders have been added (to do real time changes on your sprites) but PB doesn't support them natively yet.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 386
Joined: Thu Jul 09, 2015 9:07 am

Re: Faster vector graphics

Post by pf shadoko »

ok with Pjay
I don't think it would be difficult to do the basic graphics functions in openGL
however I couldn't make anti-aliased polygons (for lines it's ok), if someone has the solution

@ fred :
in a game you always have to update a score, and other info (speed needle for coco2)
and then you have to go through startdrawing
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Faster vector graphics

Post by netmaestro »

pf shadoko wrote:in a game you always have to update a score, and other info (speed needle for coco2)
and then you have to go through startdrawing
Use sprites for that stuff too.
BERESHEIT
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 386
Joined: Thu Jul 09, 2015 9:07 am

Re: Faster vector graphics

Post by pf shadoko »

@ netmaestro :
of course!
but startdrawing(spriteoutput(...)) is very slow (not as much as with screenoutput, but it easily drops the framerate)
see :
https://www.purebasic.fr/english/viewtopic.php?t=82923
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Faster vector graphics

Post by netmaestro »

fred wrote:When using the sprite lib, you should precalculate everything before launching your rendering loop
I'll post an example of how to do a speed indicator that uses virtually no cpu or time. It'll take me a couple hours as I have to rip code from projects but it'll be posted today.
BERESHEIT
Post Reply