Blobs! - Anyone able to speed this up?

Just starting out? Need help? Post your questions and find answers here.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by raphael.

anyone able to speed this up? maybe fred? :)
any tips appreciated!

Code: Select all

; converted from bb code
; turn debugger off for performance..

#appWidth = 640
#appHeight= 480

Structure LONG
  l.l
EndStructure

Dim Palette.l(255)
Dim table.l(#appWidth, #appWidth)

; init
Procedure.l FP_Init()
  Shared *Screen.LONG, bufferadr.l, byte_pixel.b, byte_line.l

  StartDrawing(ScreenOutput())
  StopDrawing()

  bufferadr.l = DrawingBuffer()

  byte_pixel.b = Round( ( DrawingBufferPixelFormat() + 1)/2, 1)
  byte_line.l = DrawingBufferPitch()

  *Screen.LONG = bufferadr
  
  ProcedureReturn bufferadr
EndProcedure

Procedure SetupPalette()
  ; create a temporary image...
  CreateImage(0, #appWidth, #appHeight)
  ; ...to draw a nice colour-pattern onto it
  StartDrawing(ImageOutput())
    For i = 0 To 63
     LineXY(i,0,i,200, RGB(0, 0, i*4))
    Next

    For i = 0 To 127
     LineXY(i+64,0,i+64,200, RGB(0, (i/2)*4, 63*4))
    Next

    For i = 0 To 63
     LineXY(i+192,0,i+192,200,RGB(i*4, 63*4, 63*4))
    Next
  ; grab palette data
  For x = 0 To 255
   Palette(x) = Point(x,0)
  Next
  StopDrawing()

  ; clean-up
  FreeImage(0)
EndProcedure

Procedure PreCalc()
  For y = 0 To #appHeight
   For x = 0 To #appWidth
    If x = 0 And y = 0
     table(y,x) = 255
    Else
     table(y,x) = (9000000000 / (Sqr(x*x + y*y) * 250000))
    EndIf
   Next
  Next
EndProcedure


If InitSprite() = 0
  End
EndIf

OpenWindow(0, 0, 0, #appWidth, #appHeight, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "testing...")
OpenWindowedScreen(WindowID(), 0, 0, #appWidth, #appHeight, 0, 0 ,0)

If FP_Init() = 0 : End : EndIf

SetupPalette()
PreCalc()


Repeat

  If WindowEvent() = #PB_Event_CloseWindow
    quit.b = 1
  EndIf
  
  ; fps
  If GetTickCount_() => zeit + 1000 
    FrameSek = Frames 
    Frames = 0 
    zeit = GetTickCount_() 
  Else 
    Frames + 1 
  EndIf 

  FlipBuffers()
;  ClearScreen(0,0,0)

  x1.f = 60 * Cos (alfa.f)  + 30 * Sin (-alfa)  + #appWidth/2
  y1.f = 30 * Cos (-alfa*2) + 60 * Sin (alfa)   + #appHeight/2
  x2.f = 30 * Cos (alfa)    + 60 * Sin (alfa*2) + #appWidth/2
  y2.f = 60 * Cos (alfa)    + 30 * Sin (alfa)   + #appHeight/2
  x3.f = 45 * Cos (-alfa)   + 45 * Sin (alfa)   + #appWidth/2
  y3.f = 45 * Cos (alfa*2)  + 45 * Sin (-alfa)  + #appHeight/2
  x4.f = 75 * Cos (alfa)    + 15 * Sin (alfa*2) + #appWidth/2
  y4.f = 15 * Cos (-alfa)   + 75 * Sin (alfa*2) + #appHeight/2
  x5.f = 35 * Cos (alfa)    + 10 * Sin (alfa)   + #appWidth/2
  y5.f = 10 * Cos (alfa*2)  + 35 * Sin (-alfa)  + #appHeight/2
  x6.f = 40 * Cos (-alfa)   + 30 * Sin (alfa*2) + #appWidth/2
  y6.f = 40 * Cos (alfa)    + 10 * Sin (alfa)   + #appHeight/2


  alfa.f+0.05

  For y = 0 To #appHeight ;Step 2
    For x = 0 To #appWidth
        a1.l = Abs(y1-y)
        a2.l = Abs(x1-x)
        a3.l = Abs(y2-y)
        a4.l = Abs(x2-x)
        a5.l = Abs(y3-y)
        a6.l = Abs(x3-x)
        a7.l = Abs(y4-y)
        a8.l = Abs(x4-x)
        a9.l = Abs(y5-y)
       a10.l = Abs(x5-x)
       a11.l = Abs(y6-y)
       a12.l = Abs(x6-x)

      pixel.l = table(a1, a2) + table(a3, a4) + table(a5, a6) + table(a7,a8) + table(a9, a10) + table(a11, a12)
     
      If pixel>255
        pixel=255
      EndIf

      *Screen   = bufferadr + (x * byte_pixel) + (y * byte_line)
      *Screen\l = palette(pixel)

    Next
  Next

  ; display fps
  StartDrawing(ScreenOutput())
    FrontColor(255, 255, 255)
    DrawingMode(1)
    Locate(5,452)
    DrawText("FPS: "+Str(FrameSek))
  StopDrawing()
  
;  Sleep_(5)

Until quit = 1

End
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ebs.

I gained 2 FPS by simply changing byte_pixel.b to byte_pixel.l. I think this helps because a long variable (32-bits) is the X86 native register size, and is therefore faster to manipulate.

Eric
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by webmatze.

Okay, I get now double speed! :wink:

Code: Select all

; converted from bb code; edited by webmatze
; turn debugger off for performance..

#appWidth = 640
#appHeight= 480

Structure LONG
  l.l
EndStructure

Dim Palette.l(255)
Dim table.l(#appWidth, #appWidth)

; init
Procedure.l FP_Init()
  Shared *Screen.LONG, bufferadr.l, byte_pixel.b, byte_line.l

  StartDrawing(ScreenOutput())
  StopDrawing()

  bufferadr.l = DrawingBuffer()

  byte_pixel.b = Round( ( DrawingBufferPixelFormat() + 1)/2, 1)
  byte_line.l = DrawingBufferPitch()

  *Screen.LONG = bufferadr
  
  ProcedureReturn bufferadr
EndProcedure

Procedure SetupPalette()
  ; create a temporary image...
  CreateImage(0, #appWidth, #appHeight)
  ; ...to draw a nice colour-pattern onto it
  StartDrawing(ImageOutput())
    For i = 0 To 63
     LineXY(i,0,i,200, RGB(0, 0, i*4))
    Next

    For i = 0 To 127
     LineXY(i+64,0,i+64,200, RGB(0, (i/2)*4, 63*4))
    Next

    For i = 0 To 63
     LineXY(i+192,0,i+192,200,RGB(i*4, 63*4, 63*4))
    Next
  ; grab palette data
  For x = 0 To 255
   Palette(x) = Point(x,0)
  Next
  StopDrawing()

  ; clean-up
  FreeImage(0)
EndProcedure

Procedure PreCalc()
  For y = 0 To #appHeight
   For x = 0 To #appWidth
    If x = 0 And y = 0
     table(y,x) = 255
    Else
     table(y,x) = (9000000000 / (Sqr(x*x + y*y) * 250000))
    EndIf
   Next
  Next
EndProcedure


If InitSprite() = 0
  End
EndIf

OpenWindow(0, 0, 0, #appWidth, #appHeight, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "testing...")
OpenWindowedScreen(WindowID(), 0, 0, #appWidth, #appHeight, 0, 0 ,0)

If FP_Init() = 0 : End : EndIf

SetupPalette()
PreCalc()

halfW.l = #appWidth/2
halfH.l = #appHeight/2


Repeat

  If WindowEvent() = #PB_Event_CloseWindow
    quit.b = 1
  EndIf
  
  ; fps
  If GetTickCount_() => zeit + 1000 
    FrameSek = Frames 
    Frames = 0 
    zeit = GetTickCount_() 
  Else 
    Frames + 1 
  EndIf 

  FlipBuffers()

  cosAlfa.f = Cos (alfa.f)
  cosAlfam.f = Cos (-alfa)
  cosAlfa2.f = Cos (alfa*2)
  cosAlfam2.f = Cos (-alfa*2)
  sinAlfa.f = Sin (alfa)
  sinAlfam.f = Sin (-alfa)
  sinAlfa2.f = Sin (alfa*2)
  
  x1.f = 60 * cosAlfa  + 30 * sinAlfam  + halfW
  y1.f = 30 * cosAlfam2 + 60 * sinAlfa   + halfH
  x2.f = 30 * cosAlfa    + 60 * sinAlfa2 + halfW
  y2.f = 60 * cosAlfa    + 30 * sinAlfa   + halfH
  x3.f = 45 * cosAlfam   + 45 * sinAlfa   + halfW
  y3.f = 45 * cosAlfa2  + 45 * sinAlfam  + halfH
  x4.f = 75 * cosAlfa    + 15 * sinAlfa2 + halfW
  y4.f = 15 * cosAlfam   + 75 * sinAlfa2 + halfH
  x5.f = 35 * cosAlfa    + 10 * sinAlfa   + halfW
  y5.f = 10 * cosAlfa2  + 35 * sinAlfam  + halfH
  x6.f = 40 * cosAlfam   + 30 * sinAlfa2 + halfW
  y6.f = 40 * cosAlfa    + 10 * sinAlfa   + halfH


  alfa.f+0.05

  For y = 0 To #appHeight Step 2
    For x = 0 To #appWidth Step 2
        a1.l = Abs(y1-y)
        a2.l = Abs(x1-x)
        a3.l = Abs(y2-y)
        a4.l = Abs(x2-x)
        a5.l = Abs(y3-y)
        a6.l = Abs(x3-x)
        a7.l = Abs(y4-y)
        a8.l = Abs(x4-x)
        a9.l = Abs(y5-y)
       a10.l = Abs(x5-x)
       a11.l = Abs(y6-y)
       a12.l = Abs(x6-x)

      pixel.l = table(a1, a2) + table(a3, a4) + table(a5, a6) + table(a7,a8) + table(a9, a10) + table(a11, a12)
     
      If pixel>255
        pixel=255
      EndIf

      *Screen   = bufferadr + (x * byte_pixel) + (y * byte_line)
      *Screen\l = palette(pixel)
      
      *Screen   = bufferadr + (x * byte_pixel) + ((y+1) * byte_line)
      *Screen\l = palette(pixel)
      
      *Screen   = bufferadr + ((x + 1) * byte_pixel) + (y * byte_line)
      *Screen\l = palette(pixel)

      *Screen   = bufferadr + ((x + 1) * byte_pixel) + ((y+1) * byte_line)
      *Screen\l = palette(pixel)

    Next
  Next

  StartDrawing(ScreenOutput())
    FrontColor(0, 0, 0)
    DrawingMode(0)
    Locate(5,452)
    DrawText("FPS: "+Str(FrameSek))
  StopDrawing()

Until quit = 1

End
Registered Purebasic User.
Using Windows XP on an AMD System...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ebs.

Darn - I had a bunch of little improvements (see below) like precalculating the sine/cosine values (webmatze beat me to it!), using geometry to eliminate some of the calculations (I'm a little rusty; I think I got it right), and converting the multiplications by byte_pixel and byte_line to additions.

However, it seems they hardly make any difference (maybe 2-3 FPS) compared to webmatze's "unrolling" the For/Next loops. What a good idea! :)

Here is webmatze's code with my changes incorporated:

Code: Select all

#halfW = #appWidth/2
#halfH = #appHeight/2

Repeat 
  ; fps
  If GetTickCount_() => zeit + 1000 
    FrameSek = Frames 
    Frames = 0 
    zeit = GetTickCount_() 
  Else 
    Frames + 1 
  EndIf 

  FlipBuffers()

  cosAlfa.f = Cos (alfa.f)
  cosAlfam.f = cosAlfa
;  cosAlfam.f = Cos (-alfa)
  cosAlfa2.f = Cos (alfa*2)
  cosAlfam2.f = cosAlfa2
;  cosAlfam2.f = Cos (-alfa*2)
  sinAlfa.f = Sin (alfa)
  sinAlfam.f = -sinAlfa
;  sinAlfam.f = Sin (-alfa)
  sinAlfa2.f = Sin (alfa*2)
  
  x1.f = 60 * cosAlfa  + 30 * sinAlfam  + #halfW
  y1.f = 30 * cosAlfam2 + 60 * sinAlfa   + #halfH
  x2.f = 30 * cosAlfa    + 60 * sinAlfa2 + #halfW
  y2.f = 60 * cosAlfa    + 30 * sinAlfa   + #halfH
  x3.f = 45 * cosAlfam   + 45 * sinAlfa   + #halfW
  y3.f = 45 * cosAlfa2  + 45 * sinAlfam  + #halfH
  x4.f = 75 * cosAlfa    + 15 * sinAlfa2 + #halfW
  y4.f = 15 * cosAlfam   + 75 * sinAlfa2 + #halfH
  x5.f = 35 * cosAlfa    + 10 * sinAlfa   + #halfW
  y5.f = 10 * cosAlfa2  + 35 * sinAlfam  + #halfH
  x6.f = 40 * cosAlfam   + 30 * sinAlfa2 + #halfW
  y6.f = 40 * cosAlfa    + 10 * sinAlfa   + #halfH


  alfa.f+0.05

  ybl.l = 0
  For y = 0 To #appHeight Step 2
    xbp.l = 0
    For x = 0 To #appWidth Step 2
        a1.l = Abs(y1-y)
        a2.l = Abs(x1-x)
        a3.l = Abs(y2-y)
        a4.l = Abs(x2-x)
        a5.l = Abs(y3-y)
        a6.l = Abs(x3-x)
        a7.l = Abs(y4-y)
        a8.l = Abs(x4-x)
        a9.l = Abs(y5-y)
       a10.l = Abs(x5-x)
       a11.l = Abs(y6-y)
       a12.l = Abs(x6-x)

      pixel.l = table(a1, a2) + table(a3, a4) + table(a5, a6) + table(a7,a8) + table(a9, a10) + table(a11, a12)
     
      If pixel>255
        pixel=255
      EndIf

      palpixel.l = Palette(pixel)

       *Screen   = bufferadr + xbp + ybl
       *Screen\l = palpixel  
       
       *Screen + byte_line
       *Screen\l = palpixel
 
       xbp + byte_pixel
       *Screen   = bufferadr + xbp + ybl
       *Screen\l = palpixel

       *Screen + byte_line
       *Screen\l = palpixel

    xbp + byte_pixel
    Next
    ybl + byte_line + byte_line
  Next
Eric
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.

As everyone else has posted their version here's mine which is a improvent of WebMatze's contribution..

Code: Select all

; converted from bb code
; edited by webmatze
; turn debugger off for performance..

#appWidth = 640
#appHeight= 480

Structure LONG
  l.l
EndStructure

Dim Palette.l(255)
Dim table.l(#appWidth, #appWidth)

; init
Procedure.l FP_Init()
  Shared *Screen.LONG, bufferadr.l, byte_pixel.b, byte_line.l

  StartDrawing(ScreenOutput())
  StopDrawing()

  bufferadr.l = DrawingBuffer()

  byte_pixel.b = Round( ( DrawingBufferPixelFormat() + 1)/2, 1)
  byte_line.l = DrawingBufferPitch()

  *Screen.LONG = bufferadr
  
  ProcedureReturn bufferadr
EndProcedure

Procedure SetupPalette()
  ; create a temporary image...
  CreateImage(0, #appWidth, #appHeight)
  ; ...to draw a nice colour-pattern onto it
  StartDrawing(ImageOutput())
    For i = 0 To 63
     LineXY(i,0,i,200, RGB(0, 0, i*4))
    Next

    For i = 0 To 127
     LineXY(i+64,0,i+64,200, RGB(0, (i/2)*4, 63*4))
    Next

    For i = 0 To 63
     LineXY(i+192,0,i+192,200,RGB(i*4, 63*4, 63*4))
    Next
  ; grab palette data
  For x = 0 To 255
   Palette(x) = Point(x,0)
  Next
  StopDrawing()

  ; clean-up
  FreeImage(0)
EndProcedure

Procedure PreCalc()
  For y = 0 To #appHeight
   For x = 0 To #appWidth
    If x = 0 And y = 0
     table(y,x) = 255
    Else
     table(y,x) = (9000000000 / (Sqr(x*x + y*y) * 250000))
    EndIf
   Next
  Next
EndProcedure


If InitSprite() = 0
  End
EndIf

OpenWindow(0, 0, 0, #appWidth, #appHeight, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "testing...")
OpenWindowedScreen(WindowID(), 0, 0, #appWidth, #appHeight, 0, 0 ,0)

If FP_Init() = 0 : End : EndIf

SetupPalette()
PreCalc()

halfW.l = #appWidth/2
halfH.l = #appHeight/2


Repeat

  If WindowEvent() = #PB_Event_CloseWindow
    quit.b = 1
  EndIf
  
  ; fps
  If GetTickCount_() => zeit + 1000 
    FrameSek = Frames 
    Frames = 0 
    zeit = GetTickCount_() 
  Else 
    Frames + 1 
  EndIf 

  FlipBuffers()

  cosAlfa.f = Cos (alfa.f)
  cosAlfam.f = Cos (-alfa)
  cosAlfa2.f = Cos (alfa*2)
  cosAlfam2.f = Cos (-alfa*2)
  sinAlfa.f = Sin (alfa)
  sinAlfam.f = Sin (-alfa)
  sinAlfa2.f = Sin (alfa*2)
  
  
  
  x1.f = 60 * cosAlfa  + 30 * sinAlfam  + halfW
  y1.f = 30 * cosAlfam2 + 60 * sinAlfa   + halfH
  x2.f = 30 * cosAlfa    + 60 * sinAlfa2 + halfW
  y2.f = 60 * cosAlfa    + 30 * sinAlfa   + halfH
  x3.f = 45 * cosAlfam   + 45 * sinAlfa   + halfW
  y3.f = 45 * cosAlfa2  + 45 * sinAlfam  + halfH
  x4.f = 75 * cosAlfa    + 15 * sinAlfa2 + halfW
  y4.f = 15 * cosAlfam   + 75 * sinAlfa2 + halfH
  x5.f = 35 * cosAlfa    + 10 * sinAlfa   + halfW
  y5.f = 10 * cosAlfa2  + 35 * sinAlfam  + halfH
  x6.f = 40 * cosAlfam   + 30 * sinAlfa2 + halfW
  y6.f = 40 * cosAlfa    + 10 * sinAlfa   + halfH


  alfa.f+0.05
  
  For y = 0 To #appHeight Step 2
    a1.l = Abs(y1-y)
    a3.l = Abs(y2-y)
    a5.l = Abs(y3-y)
    a7.l = Abs(y4-y)
    a9.l = Abs(y5-y)
    a11.l = Abs(y6-y)
    *screen1.LONG = bufferadr + y*byte_line
    *screen2.LONG = *screen1 + byte_line
    For x = 0 To #appWidth Step 2
        a2.l = Abs(x1-x)
        a4.l = Abs(x2-x)
        a6.l = Abs(x3-x)
        a8.l = Abs(x4-x)
       a10.l = Abs(x5-x)
       a12.l = Abs(x6-x)

      pixel.l = table(a1, a2) + table(a3, a4) + table(a5, a6) + table(a7,a8) + table(a9, a10) + table(a11, a12)
     
      If pixel>255
        pixel=255
      EndIf
      
      pixel = palette(pixel)
      
      *screen1\l = pixel
      
      *screen1 + byte_pixel
      *screen1\l = pixel

      *screen2\l = pixel
      
      *screen2 + byte_pixel
      *screen2\l = pixel
      
      *screen1 + byte_pixel
      *screen2 + byte_pixel

    Next
  Next

  StartDrawing(ScreenOutput())
    FrontColor(0, 0, 0)
    DrawingMode(0)
    Locate(5,452)
    DrawText("FPS: "+Str(FrameSek))
  StopDrawing()

Until quit = 1

End
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

i noticed this line:

Code: Select all

If GetTickCount_() => zeit + 1000
surely the comparison operator should be >= not => , it seems to work either way, is this a bug?

--Kale

In love with PureBasic! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by webmatze.

Looks more like a feature. :)

Anyway, great improvement Pupil!

Registered Purebasic User.
Using Windows XP on an AMD System...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by raphael.

thank you all! pupil, you seem to have win the competition :wink:

playing around with this 'writing directly to screenbuffer'-stuff,
i noticed purebasic's plot() was already quite fast.
i thought, fred was still about to optimise this command - did he do that already?

anyway, thanks again. cool result in the end!
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fred.

Yes, Plot() is already optimized.

Fred - AlphaSND
Post Reply