Results 1 to 32 of 32

Thread: Graphics Speed

  1. #1

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Graphics Speed

    First let me say that I am a novice at using graphics. I am writing an implementation of Conway's Game of Life Wiki Ref.. Basically you have a world of cells that can be dead or alive based on the rules given in the reference.

    My implementation:
    - I use a picturebox to show the state of the world. The image is large enough to hold a world of 269 x 269 with each cell being 3 x 3.

    - when the world is created I create a bitmap and graphics(_G) object of the appropriate size

    - the bitmap is initially filled to the dead cell color

    - To draw individual cells I use
    Code:
            _G.FillRectangle(Brush, New Rectangle(x * _BlockSize, y * _BlockSize, _BlockSize, _BlockSize))
    - The next state of the world is displayed with
    Code:
            BackGroundBM = theWorld.NextTick() 'NextTick returns the worlds bitmap
            PictureBox1.Image = BackGroundBM
    - After the initial pass I only draw cells that have changed, and process those that may have changed.

    My problem is that the drawing seems slow. Any help is appreciated.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  2. #2

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Current stats:
    With 600 alive cells and 600 changes I am getting around 30 frames per second.

    With one of the simplest patterns that has 5 alive cells, and 4 changes I get 40 FPS.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  3. #3
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    I can only theoritize about whether it woud help to speed the process up, but if you draw your black and white cells once you can save the result into an image and then invoke DrawImage instead. DrawImage should be faster for smaller images and other drawing methods should be faster if your image is big
    Also - you have a finite number of possible x and y values and possibly - a fixed blocksize. So you can precalculate all possible x * blocksize and y * blocksize and store them into an array - will save you a few ticks. General rule - all that can be calculated beforehands should be thrown over the board (put somewhere else out of the paint event handler).
    And what do you have in your BAckGroundBM? If it's just a grid then try drawing actual lines instead - it will be faster than manipulating of so big an image.

    Also - if you simply use square cells filled with color you would probably want to join adjacent cellss together into one rectangle or a graphicpath and fill the resulting figure in one pass instead of several (fill operation is the most time consuming one save only the drawing of large bitmaps).

  4. #4

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    BackGroundBM is a BitMap.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  5. #5

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    The reason I don't assign directly to the picture box is because I have an auto mode that runs in a Timer Tick event. That looks like

    Code:
                Do While Not imgReady 'is the image ready?
                    Thread.Sleep(0) 'no
                Loop
                'image ready
                PictureBox1.Image = BackGroundBM 'get it
                imgReady = False 'let the other thread get started
                Thread.Sleep(0)

    There is another thread that looks like this

    Code:
        Public Sub BackGrndNextTick()
            Do
                If Not imgReady Then
                    BackGroundBM = theWorld.NextTick
                    imgReady = True
                Else
                    If Timer1.Interval <= 20 Then Thread.Sleep(0) Else Thread.Sleep(Timer1.Interval \ 10)
                End If
            Loop While RunBKG
        End Sub
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  6. #6
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    So you're drawing your game state into a bitmap and only then copy your bitmap to the picturebox - along with all 'empty space'. Basically you copy emptiness of your game board thus eating your processor time.
    Instead, each 'generation' of your cells should have a state indicating whether the situation has changed or not. Well, probably it is always be so until your colony is degenerated into stable figures. And every time the situation has changed you should invoke the invalidate method and perform the drawing directly in the picturebox without copying empty areas on your game board.

    And I repeat - pre-calculate everything.
    Instead of using 2 multiplication operations to determine the coordinates of the upper left corner of the grid cell (6;10) you can feed your drawing procedure with pre-calculated values CellCoordsX(6), CellCoordsY(10).

  7. #7

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    I use the computation because the block size can change. I only use the FillRectangle when an individual cell changes, so in the best case scenario I posted previously there are only 4 done. With the timer tick interval set to the minimum, which really mean 10-15 ms., I can theoretically draw 100 FPS.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  8. #8

  9. #9

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    OK, I pre-computed x,y and there was not a speed improvement noticed.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  10. #10

  11. #11

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    There is no paint code to speak of. The assignment in the timer tick event I posted is it.

    As I said, in the best case scenario I am only executing the fillrectangle code (with pre-computed x,y) 4 times.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  12. #12

  13. #13
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    Try this code, it's pretty fast:
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private pic As PictureBox
    4.     Private btnStartStop As Button
    5.  
    6.     Private Running As Boolean = False
    7.  
    8.     Private Const BOARD_WIDTH As Integer = 50
    9.     Private Const BOARD_HEIGHT As Integer = 50
    10.  
    11.     Private CellSize As New SizeF
    12.  
    13.     Private cells(BOARD_WIDTH - 1, BOARD_HEIGHT - 1) As State
    14.     Private Rects(BOARD_WIDTH - 1, BOARD_HEIGHT - 1) As RectangleF
    15.    
    16.     Private linePen As New Pen(Color.Green) With {.DashStyle = Drawing2D.DashStyle.Dot}
    17.     Private CellBrush As New SolidBrush(Color.White)
    18.  
    19.  
    20.     Private Enum State
    21.         Empty = 0
    22.         Birth = 1
    23.         Alive = 2
    24.         Dying = 3
    25.     End Enum
    26.  
    27.     Public Sub New()
    28.         InitializeComponent()
    29.         Me.SuspendLayout()
    30.         pic = New PictureBox With _
    31.                 {.BackColor = Color.Black, _
    32.                  .Left = 120, .Top = 0, .Height = Me.ClientRectangle.Height, .Width = Me.ClientRectangle.Width - 120, _
    33.                  .Anchor = AnchorStyles.Bottom Or AnchorStyles.Right Or AnchorStyles.Left Or AnchorStyles.Top}
    34.         btnStartStop = New Button With _
    35.                 {.Text = "Start", .Width = 100, .Height = Me.Font.Height * 2, .Left = 10, .Top = 10}
    36.  
    37.         Me.Controls.AddRange(New Control() {pic, btnStartStop})
    38.         Me.AcceptButton = btnStartStop
    39.         Me.ResumeLayout()
    40.      
    41.  
    42.     End Sub
    43.  
    44.     Private Sub Drawing(ByVal sender As Object, ByVal e As PaintEventArgs)
    45.         Dim x, y As Single
    46.         Dim ix, iy As Integer
    47.  
    48.         For x = 0 To BOARD_WIDTH - 1
    49.             For y = 0 To BOARD_HEIGHT - 1
    50.                 ix = CInt(x)
    51.                 iy = CInt(y)
    52.                 Select Case cells(ix, iy)
    53.                     Case State.Dying
    54.                         cells(ix, iy) = State.Empty
    55.                     Case State.Birth
    56.                         cells(ix, iy) = State.Alive
    57.                 End Select
    58.                 If cells(CInt(x), CInt(y)) = State.Alive Then e.Graphics.FillRectangle(CellBrush, Rects(CInt(x), CInt(y)))
    59.             Next
    60.         Next
    61.  
    62.         For x = 0 To pic.ClientRectangle.Width - 1 Step CellSize.Width
    63.             e.Graphics.DrawLine(linePen, x, 0, x, pic.ClientRectangle.Height - 1)
    64.         Next
    65.         For y = 0 To pic.ClientRectangle.Height - 1 Step CellSize.Height
    66.             e.Graphics.DrawLine(linePen, 0, y, pic.ClientRectangle.Width - 1, y)
    67.         Next
    68.     End Sub
    69.  
    70.  
    71.     Private Sub StartStop(ByVal sender As Object, ByVal e As EventArgs)
    72.         Running = Not Running
    73.         If Running Then
    74.             btnStartStop.Text = "Stop"
    75.             RemoveHandler pic.MouseClick, AddressOf UserClick
    76.         Else
    77.             btnStartStop.Text = "Start"
    78.             AddHandler pic.MouseClick, AddressOf UserClick
    79.         End If
    80.         If Running Then GoForthAndMultiply()
    81.     End Sub
    82.  
    83.     Private Sub GoForthAndMultiply()
    84.         Do
    85.             Application.DoEvents()
    86.             Generation()
    87.             pic.Invalidate()
    88.             If Running = False Then Exit Sub
    89.         Loop
    90.     End Sub
    91.  
    92.     Private Sub Generation()
    93.         ' cell dies if it has less than 2 or more than 3 neighbors
    94.         ' cell is born if it has exactly 3 neighbors
    95.         Dim x, y As Integer
    96.         Dim Neighbors As Integer = 0
    97.  
    98.  
    99.         For x = 0 To BOARD_WIDTH - 1
    100.             For y = 0 To BOARD_HEIGHT - 1
    101.                 If y > 0 AndAlso cells(x, y - 1) >= State.Alive Then Neighbors += 1
    102.                 If y > 0 AndAlso x < (BOARD_WIDTH - 1) AndAlso cells(x + 1, y - 1) >= State.Alive Then Neighbors += 1
    103.                 If x < (BOARD_WIDTH - 1) AndAlso cells(x + 1, y) >= State.Alive Then Neighbors += 1
    104.                 If x < (BOARD_WIDTH - 1) AndAlso y < (BOARD_HEIGHT - 1) AndAlso cells(x + 1, y + 1) >= State.Alive Then Neighbors += 1
    105.                 If y < (BOARD_HEIGHT - 1) AndAlso cells(x, y + 1) >= State.Alive Then Neighbors += 1
    106.                 If x > 0 AndAlso y < (BOARD_HEIGHT - 1) AndAlso cells(x - 1, y + 1) >= State.Alive Then Neighbors += 1
    107.                 If x > 0 AndAlso cells(x - 1, y) >= State.Alive Then Neighbors += 1
    108.                 If x > 0 AndAlso y > 0 AndAlso cells(x - 1, y - 1) >= State.Alive Then Neighbors += 1
    109.  
    110.                 Select Case Neighbors
    111.                     Case 0, 1, Is > 3
    112.                         If cells(x, y) <> State.Empty Then cells(x, y) = State.Dying
    113.                     Case 3
    114.                         If cells(x, y) = State.Empty Then cells(x, y) = State.Birth
    115.                 End Select
    116.                 Neighbors = 0
    117.             Next
    118.         Next
    119.     End Sub
    120.  
    121.     Private Sub UserClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    122.         Dim cell As New Point
    123.         Dim x, y As Integer
    124.         x = CInt(Fix((e.X / CellSize.Width)))
    125.         y = CInt(Fix((e.Y / CellSize.Height)))
    126.  
    127.         Select Case cells(x, y)
    128.             Case State.Alive, State.Dying
    129.                 cells(x, y) = State.Empty
    130.             Case State.Empty, State.Birth
    131.                 cells(x, y) = State.Alive
    132.         End Select
    133.  
    134.         pic.Invalidate()
    135.     End Sub
    136.  
    137.     Private Sub SetCellSize()
    138.         Dim w, h As Single
    139.         w = CSng(pic.ClientRectangle.Width / BOARD_WIDTH)
    140.         h = CSng(pic.ClientRectangle.Height / BOARD_HEIGHT)
    141.  
    142.         Dim x, y As Integer
    143.         For y = 0 To BOARD_HEIGHT - 1
    144.             For x = 0 To BOARD_WIDTH - 1
    145.                 Rects(x, y) = New RectangleF(x * w, y * h, w, h)
    146.             Next
    147.         Next
    148.         CellSize.Width = w
    149.         CellSize.Height = h
    150.  
    151.     End Sub
    152.  
    153.     Private Sub Pic_Resize(ByVal sender As Object, ByVal e As System.EventArgs)
    154.         SetCellSize()
    155.         pic.Invalidate()
    156.     End Sub
    157.  
    158.     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    159.         AddHandler btnStartStop.Click, AddressOf StartStop
    160.         AddHandler pic.Paint, AddressOf Drawing
    161.         AddHandler pic.MouseClick, AddressOf UserClick
    162.         AddHandler pic.Resize, AddressOf Pic_Resize
    163.         SetCellSize()
    164.     End Sub
    165. End Class

  14. #14
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    With grid lines it run with avg fps =25 in full screen mode, without grid lines it was around 100 frames per second (also in full screen - with default form size the fps was up to 320).

  15. #15
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628

    Re: Graphics Speed

    the issue is the timer in my opinion. zero execution time would give you a best of 100 frames/sec. You should research a game loop. I was bottlenecking framerates on a simple game as well and when i removed the timer and put a do loop in with getasynckeystate to check for keypresses to exit, my framerate increased by a factor of ten.

    as a side note, it's possible to only invalidate the region of the screen that changed instead of the whole thing. Yeah you are only changing certain parts when you paint it, but unless you tell windows otherwise with clip regions, it will still redraw the entire image every time a single part of it changes.
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

  16. #16

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Quote Originally Posted by cicatrix View Post
    Try this code, it's pretty fast:
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private pic As PictureBox
    4.     Private btnStartStop As Button
    5.  
    6.     Private Running As Boolean = False
    7.  
    8.     Private Const BOARD_WIDTH As Integer = 50
    9.     Private Const BOARD_HEIGHT As Integer = 50
    10.  
    11.     Private CellSize As New SizeF
    12.  
    13.     Private cells(BOARD_WIDTH - 1, BOARD_HEIGHT - 1) As State
    14.     Private Rects(BOARD_WIDTH - 1, BOARD_HEIGHT - 1) As RectangleF
    15.    
    16.     Private linePen As New Pen(Color.Green) With {.DashStyle = Drawing2D.DashStyle.Dot}
    17.     Private CellBrush As New SolidBrush(Color.White)
    18.  
    19.  
    20.     Private Enum State
    21.         Empty = 0
    22.         Birth = 1
    23.         Alive = 2
    24.         Dying = 3
    25.     End Enum
    26.  
    27.     Public Sub New()
    28.         InitializeComponent()
    29.         Me.SuspendLayout()
    30.         pic = New PictureBox With _
    31.                 {.BackColor = Color.Black, _
    32.                  .Left = 120, .Top = 0, .Height = Me.ClientRectangle.Height, .Width = Me.ClientRectangle.Width - 120, _
    33.                  .Anchor = AnchorStyles.Bottom Or AnchorStyles.Right Or AnchorStyles.Left Or AnchorStyles.Top}
    34.         btnStartStop = New Button With _
    35.                 {.Text = "Start", .Width = 100, .Height = Me.Font.Height * 2, .Left = 10, .Top = 10}
    36.  
    37.         Me.Controls.AddRange(New Control() {pic, btnStartStop})
    38.         Me.AcceptButton = btnStartStop
    39.         Me.ResumeLayout()
    40.      
    41.  
    42.     End Sub
    43.  
    44.     Private Sub Drawing(ByVal sender As Object, ByVal e As PaintEventArgs)
    45.         Dim x, y As Single
    46.         Dim ix, iy As Integer
    47.  
    48.         For x = 0 To BOARD_WIDTH - 1
    49.             For y = 0 To BOARD_HEIGHT - 1
    50.                 ix = CInt(x)
    51.                 iy = CInt(y)
    52.                 Select Case cells(ix, iy)
    53.                     Case State.Dying
    54.                         cells(ix, iy) = State.Empty
    55.                     Case State.Birth
    56.                         cells(ix, iy) = State.Alive
    57.                 End Select
    58.                 If cells(CInt(x), CInt(y)) = State.Alive Then e.Graphics.FillRectangle(CellBrush, Rects(CInt(x), CInt(y)))
    59.             Next
    60.         Next
    61.  
    62.         For x = 0 To pic.ClientRectangle.Width - 1 Step CellSize.Width
    63.             e.Graphics.DrawLine(linePen, x, 0, x, pic.ClientRectangle.Height - 1)
    64.         Next
    65.         For y = 0 To pic.ClientRectangle.Height - 1 Step CellSize.Height
    66.             e.Graphics.DrawLine(linePen, 0, y, pic.ClientRectangle.Width - 1, y)
    67.         Next
    68.     End Sub
    69.  
    70.  
    71.     Private Sub StartStop(ByVal sender As Object, ByVal e As EventArgs)
    72.         Running = Not Running
    73.         If Running Then
    74.             btnStartStop.Text = "Stop"
    75.             RemoveHandler pic.MouseClick, AddressOf UserClick
    76.         Else
    77.             btnStartStop.Text = "Start"
    78.             AddHandler pic.MouseClick, AddressOf UserClick
    79.         End If
    80.         If Running Then GoForthAndMultiply()
    81.     End Sub
    82.  
    83.     Private Sub GoForthAndMultiply()
    84.         Do
    85.             Application.DoEvents()
    86.             Generation()
    87.             pic.Invalidate()
    88.             If Running = False Then Exit Sub
    89.         Loop
    90.     End Sub
    91.  
    92.     Private Sub Generation()
    93.         ' cell dies if it has less than 2 or more than 3 neighbors
    94.         ' cell is born if it has exactly 3 neighbors
    95.         Dim x, y As Integer
    96.         Dim Neighbors As Integer = 0
    97.  
    98.  
    99.         For x = 0 To BOARD_WIDTH - 1
    100.             For y = 0 To BOARD_HEIGHT - 1
    101.                 If y > 0 AndAlso cells(x, y - 1) >= State.Alive Then Neighbors += 1
    102.                 If y > 0 AndAlso x < (BOARD_WIDTH - 1) AndAlso cells(x + 1, y - 1) >= State.Alive Then Neighbors += 1
    103.                 If x < (BOARD_WIDTH - 1) AndAlso cells(x + 1, y) >= State.Alive Then Neighbors += 1
    104.                 If x < (BOARD_WIDTH - 1) AndAlso y < (BOARD_HEIGHT - 1) AndAlso cells(x + 1, y + 1) >= State.Alive Then Neighbors += 1
    105.                 If y < (BOARD_HEIGHT - 1) AndAlso cells(x, y + 1) >= State.Alive Then Neighbors += 1
    106.                 If x > 0 AndAlso y < (BOARD_HEIGHT - 1) AndAlso cells(x - 1, y + 1) >= State.Alive Then Neighbors += 1
    107.                 If x > 0 AndAlso cells(x - 1, y) >= State.Alive Then Neighbors += 1
    108.                 If x > 0 AndAlso y > 0 AndAlso cells(x - 1, y - 1) >= State.Alive Then Neighbors += 1
    109.  
    110.                 Select Case Neighbors
    111.                     Case 0, 1, Is > 3
    112.                         If cells(x, y) <> State.Empty Then cells(x, y) = State.Dying
    113.                     Case 3
    114.                         If cells(x, y) = State.Empty Then cells(x, y) = State.Birth
    115.                 End Select
    116.                 Neighbors = 0
    117.             Next
    118.         Next
    119.     End Sub
    120.  
    121.     Private Sub UserClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    122.         Dim cell As New Point
    123.         Dim x, y As Integer
    124.         x = CInt(Fix((e.X / CellSize.Width)))
    125.         y = CInt(Fix((e.Y / CellSize.Height)))
    126.  
    127.         Select Case cells(x, y)
    128.             Case State.Alive, State.Dying
    129.                 cells(x, y) = State.Empty
    130.             Case State.Empty, State.Birth
    131.                 cells(x, y) = State.Alive
    132.         End Select
    133.  
    134.         pic.Invalidate()
    135.     End Sub
    136.  
    137.     Private Sub SetCellSize()
    138.         Dim w, h As Single
    139.         w = CSng(pic.ClientRectangle.Width / BOARD_WIDTH)
    140.         h = CSng(pic.ClientRectangle.Height / BOARD_HEIGHT)
    141.  
    142.         Dim x, y As Integer
    143.         For y = 0 To BOARD_HEIGHT - 1
    144.             For x = 0 To BOARD_WIDTH - 1
    145.                 Rects(x, y) = New RectangleF(x * w, y * h, w, h)
    146.             Next
    147.         Next
    148.         CellSize.Width = w
    149.         CellSize.Height = h
    150.  
    151.     End Sub
    152.  
    153.     Private Sub Pic_Resize(ByVal sender As Object, ByVal e As System.EventArgs)
    154.         SetCellSize()
    155.         pic.Invalidate()
    156.     End Sub
    157.  
    158.     Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    159.         AddHandler btnStartStop.Click, AddressOf StartStop
    160.         AddHandler pic.Paint, AddressOf Drawing
    161.         AddHandler pic.MouseClick, AddressOf UserClick
    162.         AddHandler pic.Resize, AddressOf Pic_Resize
    163.         SetCellSize()
    164.     End Sub
    165. End Class
    How does it do with a height / width of 269 and a cell of 3 x 3? How many frames per second?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  17. #17

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    If I comment this

    Code:
                PictureBox1.Image = BackGroundBM
    out of the timer it runs at 100 FPS.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  18. #18
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Graphics Speed

    I think that the actual drawing code takes negligible time to execute. It's the actual drawing (done by windows I guess) that takes so much time.

    If you don't set the picturebox image, then the drawing code is executed, but it is never actually drawn so you are only seeing a very minor delay. As soon as you set the image of the picturebox however, it needs to be drawn, and this is what takes so much time.

    That's why, when calling Invalidate, you should always try to minimize the region that is invalidated. You can do that by passing a rectangle, or Region, or possibly other structures, to the Invalidate function. Then, only that region is painted, and of course it takes less time to draw a small region.

    I've wondered about this before, but I guess it makes sense. If you have some drawing code (in a Paint event), then that code is executed entirely every time the paint event is called. But that doesn't mean that all of it is actually drawn to the screen. If you call Invalidate with only a tiny rectangle, then only that rectangle is repainted (even though the entire Paint code is executed). This takes much less time than painting the entire thing in one go.



    If you look at my game of life example, you'll notice the same behavior. If you choose a large grid size (say 150x150) then it takes quite a lot of time to draw the grid initially (try loading a file of 150x150 for example). But when you run the simulation, the cells are drawn virtually at constant speed (10 times per second because the timer is at 100 ms interval). This is because I am only invalidating the areas on the grid that actually change (eg: the bounds of the cells that change). If I had it repaint the entire grid every 'tick', it would run extremely slow.

  19. #19

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Here is a pattern that should start small and fill up the screen.

    Code:
    #Life 1.05
    
    #D Small spacefiller drawn by spaceships.
    
    #D A 187 point rotationally symmetric spacefiller with
    
    #D flipper stretchers in place of the normally period
    
    #D 2 stretchers.  The pattern on the interior of this
    
    #D spacefiller is forced by the stabilization requirements.
    
    #D This spacefiller also exists in a vertically reflected
    
    #D symmetric form that also has 187 points.  By Tim Coe.
    
    #N
    
    #P -17 -12
    
    .............***...***
    
    ............*..*...*..*
    
    ...............*...*
    
    ...............*...*
    
    .*.............*...*
    
    *............................******
    
    *.....*......***...***......*.....*
    
    ******........*..*..*.............*
    
    ........*.....*.***.**.....*.....*
    
    ........*....*............*.*
    
    ....****....********.**.**
    
    ...*****........*..*...*.*....**
    
    ..**.***...****..*..****...***.**
    
    ...**....*.*...*..*........*****
    
    .........**.**.********....****
    
    ......*.*............*....*
    
    .*.....*.....**.***.*.....*
    
    *.............*..*..*........******
    
    *.....*......***...***......*.....*
    
    ******............................*
    
    ...............*...*.............*
    
    ...............*...*
    
    ...............*...*
    
    ............*..*...*..*
    
    .............***...***
    With a 273 x 273 grid, cell dimension of 3 x 3, how well does your method run?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  20. #20

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    With this pattern

    Code:
    ***
    
    ..*
    
    .*
    at the same dimensions I am getting between 35-40 FPS.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  21. #21
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    Quote Originally Posted by dbasnett View Post
    How does it do with a height / width of 269 and a cell of 3 x 3? How many frames per second?
    Around 28 FPS (without grid)

  22. #22
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Graphics Speed

    My simulator can't read those files. I am saving simply text files with 0 for dead and 1 for alive cells. A 273x273 grid is quite large though, I think it will be slow.

    Also, mine doesn't try to go as fast as possible. I'm just using a timer set at 100 ms interval which calculates the new grid every tick. I just tried a grid of 273x273 with 3x3 cells and it sure didn't run at 100 ms interval though. More like twice per second which would be 500 ms, so there's a large delay.

    I wasn't saying my simulator was faster than yours (I didn't try yours yet), I am merely saying that painting just the changed cells will be hell of a lot faster than painting the entire grid.

    Just for the fun of it I tried it again (273x273) without painting just the changed cells. This time, I am painting the whole grid each timer tick. It takes about 5 seconds to draw the new grid where it should run at 0.1 seconds.

  23. #23

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Quote Originally Posted by cicatrix View Post
    Around 28 FPS (without grid)
    Which pattern?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  24. #24

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Quote Originally Posted by NickThissen View Post
    My simulator can't read those files. I am saving simply text files with 0 for dead and 1 for alive cells. A 273x273 grid is quite large though, I think it will be slow.

    Also, mine doesn't try to go as fast as possible. I'm just using a timer set at 100 ms interval which calculates the new grid every tick. I just tried a grid of 273x273 with 3x3 cells and it sure didn't run at 100 ms interval though. More like twice per second which would be 500 ms, so there's a large delay.

    I wasn't saying my simulator was faster than yours (I didn't try yours yet), I am merely saying that painting just the changed cells will be hell of a lot faster than painting the entire grid.

    Just for the fun of it I tried it again (273x273) without painting just the changed cells. This time, I am painting the whole grid each timer tick. It takes about 5 seconds to draw the new grid where it should run at 0.1 seconds.
    I have some code that stores x,y,DeadAlive in a list of just the cells that changed. When I added code to pull the data from the list and just draw those cells in the paint event, the speed was about the same.

    Code:
         For z = 0 To lDP.Count - 1
                    If lDP(z).OnOff Then
                        e.FillRectangle(_OBrush, lDP(z).X, lDP(z).Y, _BlockSize, _BlockSize)
                    Else
                        e.FillRectangle(_NOBrush, lDP(z).X, lDP(z).Y, _BlockSize, _BlockSize)
                    End If
                Next
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  25. #25
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Graphics Speed

    But that is besides the point. You may be calling FillRectangle only on the changed cells, but if you call Invalidate (without specifying a region), or setting the Image of the picturebox, the whole image will be painted regardless.

    If you have some code in your paint event that simply paints the backcolor of the picturebox with a random color each time. Then when you call Invalidate without parameters, the whole picturebox will be painted in a random color. If you call Invalidate with a small rectangle though, then only that rectangle will get a new (random) color. The rest stays the old color, because it is never repainted. It will eventually get repainted (when the window is repainted, when you drag something over it, when you resize it, etc), but that is outside of your control.

    The point is that calling Invalidate without a rectangle (letting it paint the entire picturebox) takes longer than calling it with a rectangle (letting it paint only the specified rectangle), even if the paint code is the same (just a single call to FillRectangle). Of course, with this random color example you won't notice the difference unless the form is huge, but still.

  26. #26
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Graphics Speed

    Quote Originally Posted by dbasnett View Post
    Which pattern?
    Just some random clicks (pretty many of clicks in order to get a lively population).
    I used 300x300 board and the dots were very small - even on full screen. I experimented with the board size and I think that 50x50 is probably an optimum dimensions. Well, maybe 100x100 will do, but is it really necessary?

    Tell me, why use timers at all? In a graphics app where you use FPS to measure performance?
    Mine just enters the loop and redraws as soon a life cycle is completed - the sooner the better. Every frame is a new generation or I don't have to redraw the screen do I? Look at how DirectX works - it just refreshes the presentation in a loop - no timers.

  27. #27

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Quote Originally Posted by cicatrix View Post
    Just some random clicks (pretty many of clicks in order to get a lively population).
    I used 300x300 board and the dots were very small - even on full screen. I experimented with the board size and I think that 50x50 is probably an optimum dimensions. Well, maybe 100x100 will do, but is it really necessary?

    Tell me, why use timers at all? In a graphics app where you use FPS to measure performance?
    Mine just enters the loop and redraws as soon a life cycle is completed - the sooner the better. Every frame is a new generation or I don't have to redraw the screen do I? Look at how DirectX works - it just refreshes the presentation in a loop - no timers.
    There are a lot of existing patterns, and a fair number of them want a world of a large size.

    When I started with the timer business it was simply to advance to the next cycle once per second automatically, and then, being a manly man and all, it progressed to how fast. Of course the underlying premise of a life every controlled period remains.

    After messing with this for hours I have discovered that when the number of changes in a cycle is small, drawing the individual cells is faster than re-drawing the entire world. In my case that number is 500-600. So what I did is to make a decision based on frame rate. I draw the individual cells until the rate drops below 30 FPS. When less than 30 FPS I draw the entire world. I am still playing with it, but will post soon.

    So with this pattern (which I posted earlier)

    Code:
    ***
    
    ..*
    
    .*
    I am now able to run it at 100 FPS, which is the max using a timer.
    Last edited by dbasnett; Feb 20th, 2010 at 01:42 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  28. #28

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Latest in my quest to better understand this.

    The code that only drew the cells that changed was invalidating that rectangle as soon as it was drawn. I added another rectangle and made it the union of itself and the rectangle just drawn.

    After all of the cells have been drawn I now invalidate the union.

    Code:
                'accumulate all Rect and when finished invalidate
                If Not RUnions.IsEmpty Then RUnions = Rectangle.Union(RUnions, Rect) Else RUnions = Rect
            Next
    
            PictureBox1.Invalidate(RUnions) 'draw them
    I tried doing the same thing with regions, but it seemed slower.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  29. #29
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Graphics Speed

    If my understanding of Invalidate is correct, then you shouldn't need to do that.

    For one, suppose only the top-left cell and the bottom-right cell have changed. Then, the union of those two cells is the entire grid, so you are still painting the entire grid! I'm not sure if regions have that problem too (I don't think so, I think a region can have two disconnected rectangles, right?) so I would think it would be faster with regions (although regions might be slower for a different reason).

    But more importantly, as far as I understand it, Invalidate will not immediately repaint the picturebox. It will merely place the region to invalidate in some sort of queue. If you call Invalidate successively in a quick loop, then it will place all those regions in the queue, and once you call Update (or if you wait a little while for the paint message to get through), all those invalidated regions will be repainted in one go.

    So, calling invalidate once with the total rectangle, or calling it 10000 times with a small part of that rectangle each time should not make a difference, at least not in painting time. Only when you call Update does the control paint all its invalidated regions.


    So, what you are doing now (placing each rectangle to invalidate in a union of rectangles) is more or less what the framework already provides for you, except that a union of all rectangles isn't a very good way to form the 'queue' of areas to paint.

  30. #30

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Believe me I am over my head here. I believe what you said, and that is what I think also. I am not certain why it is faster for that reason, but it is.

    Like I said in my first post, I am a novice at graphics, and still am because the results don't make sense to me.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  31. #31

  32. #32

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Graphics Speed

    Well, the entire project, with about 130 patterns, is here.

    http://www.vbforums.com/showthread.php?t=603846

    @nick /cica - thanks for your input.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width