View Full Version : Variable graphics speed at Canvas_Window
paravantis
05-08-2015, 09:55
Hello all from a newbie at thinBasic (although an old hand at programming.)
I am interested in writing code for Agent-Based Modeling of complex systems (like Netlogo) and have been impressed with thinBasic's coverage and overall speed.
I have come across an issue that I would like to get your feedback on: drawing repetitive graphics on a canvas_window runs faster when the window menu (top left corner) is invoked.
Take a look at my following code. It opens a window with an empty title that covers the entire desktop and draws red boxes of various hues on it. If a key is pressed, the program exits. Observe that the boxes are drawn faster if one presses ALT, which activates the window menu. This happens even if the Canvas_Inkey line is commented out so it is not due to the windows expecting user input.
Can you help?
Uses "UI"
/* Uses "Console" */
Const s As Long Value 25 ' SIZE OF RECTANGLE DRAWN
Dim xDesk,yDesk As Long
Dim xMin,yMin,xMax,yMax As Long
Dim hWin As Long
Dim x,y As Long
Dim r1,r2,r3 As Long
' GRAB DESKTOP SIZE
Desktop Get Size To xDesk,yDesk
/* Print xMax,yMax */
' EMPTY TITLE MAKES WINDOW
' HAVE NO TITLE Bar
' AND COVER ALL DESKTOP!
hWin = Canvas_Window("Try",0,0,xDesk,yDesk)
' NOW SET DRAW AREA
xMin=1
yMin=1
xMax=xDesk-Max(12,s+2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ RIGHT MARGIN
yMax=yDesk-Max(12,s+2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ BOTTOM MARGIN
/* MousePtr(0) */
Do
If Canvas_Inkey<>"" Then Stop
x=Rnd(xMin,xMax)
y=Rnd(xMin,yMax)
r1=Rnd(100,200)
/* Canvas_SetPixel(x,y,Rgb(r1,r1,r1)) */
Canvas_Box(x,y,x+s,y+s,0,Rgb(r1,0,0),Rgb(r1,0,0))
Loop
/* MsgBox 0, "GRAPHICS DEMO",%MB_ICONASTERISK,"Testing canvas windows" */
ErosOlmi
05-08-2015, 18:06
Ciao paravantis and welcome to thinBasic community.
I can confirm that this is an issue introduced by the latest version of the compiler (PowerBasic 10.x) I use to develop thinBasic.
Other users in the compiler forum has reported the same problem.
At the moment there is no a solution and there are no workarounds I'm aware.
The only way I can have to solve the problem is dividing UI (thinBasic User Interface module) into 2 different DLL moving all CANVASS_* functions into a new module and compile it with previous compiler version and see if this makes any difference.
Will see what I can do when I will come back from holidays.
Ciao
Eros
Petr Schreiber
05-08-2015, 21:08
The key to best performance is to use double buffering - it will allow you to have updates more under control, and without flicker.
Check out this modification:
Uses "UI"
/* Uses "Console" */
%s = 25 ' SIZE OF RECTANGLE DRAWN
Long xDesk, yDesk
Long xMin, yMin, xMax, yMax
Long x,y
Long r1, r2, r3
' GRAB DESKTOP SIZE
Desktop Get Size To xDesk,yDesk
/* Print xMax,yMax */
' EMPTY TITLE MAKES WINDOW
' HAVE NO TITLE Bar
' AND COVER ALL DESKTOP!
DWord hWin = Canvas_Window("Try",0,0,xDesk,yDesk)
Canvas_Attach(hWin, 0, TRUE) ' -- True enables double buffering
' NOW SET DRAW AREA
xMin= 1
yMin= 1
xMax= xDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ RIGHT MARGIN
yMax= yDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ BOTTOM MARGIN
/* MousePtr(0) */
Long i
Do
If Canvas_Inkey <> "" Then Stop
For i = 1 To 1000
x=Rnd(xMin,xMax)
y=Rnd(xMin,yMax)
r1=Rnd(100,200)
/* Canvas_SetPixel(x,y,Rgb(r1,r1,r1)) */
Canvas_Box(x,y,x+%s,y+%s,0,Rgb(r1,0,0),Rgb(r1,0,0))
Next
Canvas_Redraw ' -- Updates screen at once
Loop
Petr
Petr Schreiber
05-08-2015, 21:18
...and little variation, using hardware acceleration:
Uses "TBGL"
%s = 25 ' SIZE OF RECTANGLE DRAWN
Long xDesk, yDesk, bitDepth
Long xMin, yMin, xMax, yMax
Long x,y
Long r1, r2, r3
' GRAB DESKTOP SIZE
TBGL_GetDesktopInfo(xDesk, yDesk, bitDepth)
Long fullScreen = FALSE
DWord hWin = TBGL_CreateWindowEx("Try", xDesk, yDesk, bitDepth, IIf(fullScreen, %TBGL_WS_FULLSCREEN, %TBGL_WS_WINDOWED))
TBGL_ShowWindow
' NOW SET DRAW AREA
xMin= 1
yMin= 1
xMax= xDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ RIGHT MARGIN
yMax= yDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ BOTTOM MARGIN
Long i
TBGL_RenderMatrix2D
TBGL_BackColor(255, 255, 255)
While TBGL_IsWindow(hWin)
TBGL_ClearFrame
For i = 1 To 10000
x=Rnd(xMin,xMax)
y=Rnd(xMin,yMax)
r1=Rnd(100,200)
TBGL_Color r1, 0, 0
TBGL_Rect(x, y, x+%s, y+%s)
Next
TBGL_DrawFrame
If TBGL_GetWindowKeyState(hWin, %VK_ESCAPE) Then
Exit While
End If
Wend
TBGL_DestroyWindow
ErosOlmi
06-08-2015, 01:11
Thanks Petr for great examples.
In the above CANVASS_* examples, better to substitute the line
Do
...
Loop
with
Do While IsWindow(hWin)
...
Loop
In this way the process will be closed when the window will be closed.
Otherwise it could be possible to close the window and the process will still working in the background and you would need Task Manager to close it.
paravantis
06-08-2015, 23:21
Thank you very much gentlemen!
Eros, I am very pleasantly taken aback by your quick response and kind willingness to try out a solution with the previous version of the POWERBASIC compiler. Much obliged Sir. You even solved another issue I had: I now realize that checking whether the window is still open at the loop, is the proper way to implement this code - I had noticed that closing the window did not kill thinBasic.exe and was wondering about it.
Petr, your 3D example runs amazingly fast and has wetted my appetite for learning TBGL. I do have one question though: the
TBGL_ClearFrame
command clears the TBGL canvas every time it is called - this is not what I want. I want previous graphics to stick to the canvas. With the very little I know of TBGL now (but I will improve fast), I could not make graphics stick, e.g. by moving the command before the while loop. Can it be done?
Petr Schreiber
07-08-2015, 23:36
Good question!
There are multiple possible approaches to "sticking", I would say the most reasonable one would be rendering to texture.
Basically, what you render in one frame, you copy to texture, then use this texture as background in next frame and add something new.
Sounds horrible? I wrapped it in AdditiveDrawing object for you, it's easy!
Try this example - I reduced the number of added boxes to 10 per frame, so you can see how it fills in:
Uses "TBGL"
%s = 25 ' SIZE OF RECTANGLE DRAWN
Long xDesk, yDesk,bitDepth
Long xMin, yMin, xMax, yMax
Long x,y
Long r1, r2, r3
' GRAB DESKTOP SIZE
'TBGL_GetDesktopInfo(xDesk,yDesk,bitDepth) ' -- Not sure if your GPU can manage, feel free to experiment
xDesk = 512
yDesk = 512
DWord hWin = TBGL_CreateWindowEx("Try", xDesk, yDesk, 32, %TBGL_WS_WINDOWED)
TBGL_ShowWindow
' NOW SET DRAW AREA
xMin= 1
yMin= 1
xMax= xDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ RIGHT MARGIN
yMax= yDesk - Max(12, %s + 2) ' MAKE SURE THERE IS ENOUGH SPACE FOR RECTANGLES @ BOTTOM MARGIN
Long i
TBGL_RenderMatrix2D
TBGL_BackColor(255, 255, 255)
Type AdditiveDrawing
_textureSlot As Long
_width As Long
_height As Long
Init As Function
DrawLast As Function
Update As Function
End Type
Dim drawing As AdditiveDrawing
drawing.Init(hWin, 1)
While TBGL_IsWindow(hWin)
TBGL_ClearFrame
' -- Draw previous stuff
drawing.drawLast()
' -- Draw new stuff
For i = 1 To 10
x=Rnd(xMin,xMax)
y=Rnd(xMin,yMax)
r1=Rnd(100,200)
TBGL_Color r1, 0, 0
TBGL_Rect(x, y, x+%s, y+%s)
Next
' -- Store new image
drawing.update()
TBGL_DrawFrame
If TBGL_GetWindowKeyState(hWin, %VK_ESCAPE) Then
Exit While
End If
Wend
TBGL_DestroyWindow
' -- Auxiliary methods
Function AdditiveDrawing.Init( hWnd As DWord, textureSlot As Long )
TBGL_GetWindowClient(hWin, Me._width, Me._height)
Me._textureSlot = textureSlot
TBGL_MakeTexture Repeat$(Me._width * Me._height, MKBYT$(255, 255, 255, 255)), %TBGL_DATA_BGRA, Me._width, Me._height, Me._textureSlot, %TBGL_TEX_NEAREST
End Function
Function AdditiveDrawing.DrawLast()
TBGL_PushStateProtect %TBGL_DEPTH
TBGL_PushColor 255, 255, 255
TBGL_PushState %TBGL_TEXTURING
TBGL_PushTexture 1
TBGL_BeginPoly %GL_QUADS
TBGL_TexCoord2D 0, 0
TBGL_Vertex 0, 0
TBGL_TexCoord2D 1, 0
TBGL_Vertex Me._width, 0
TBGL_TexCoord2D 1, 1
TBGL_Vertex Me._width, Me._height
TBGL_TexCoord2D 0, 1
TBGL_Vertex 0, Me._height
TBGL_EndPoly
TBGL_PopTexture
TBGL_PopState
TBGL_PopColor
TBGL_PopStateProtect
End Function
Function AdditiveDrawing.Update()
TBGL_RenderToTexture( Me._textureSlot, 0, 0, Me._width, Me._height )
End Function
Petr