ffweb
New Member
Posts: 20
|
Post by ffweb on May 30, 2011 21:44:55 GMT 1
I think that a true BASIC needs an easy access to graphics, to allow hobby programmers like me to play around. I played a bit with SDL libraries and ended with this (don't expect too much):
Include file SDLgraphics.bac:
' Easy graphic functions built on top of SDL ' ' (FFweb) '
TRAP LOCAL
SDL_LIB$ = "libSDL.so"
CONST SDL_DEPTH = 24 CONST SDL_SWSURFACE = 0x00000000 CONST SDL_HWSURFACE = 0x00000001
' Same as SDL_Rect RECORD SDLRECT LOCAL x TYPE int16_t LOCAL y TYPE int16_t LOCAL w TYPE uint16_t LOCAL h TYPE uint16_t END RECORD
' To store window dimensions RECORD SDLWINSIZE LOCAL w TYPE int LOCAL h TYPE int END RECORD
GLOBAL SDLSCREEN TYPE long GLOBAL SDLCOLOR TYPE uint32_t
IMPORT "SDL_Init" FROM SDL_LIB$ TYPE void IMPORT "SDL_MapRGB" FROM SDL_LIB$ TYPE void IMPORT "SDL_SetVideoMode" FROM SDL_LIB$ TYPE long IMPORT "SDL_FillRect" FROM SDL_LIB$ TYPE int IMPORT "SDL_Flip" FROM SDL_LIB$ TYPE void IMPORT "SDL_Quit" FROM SDL_LIB$ TYPE void
' Create graphical screen FUNCTION MAKEWINDOW(NUMBER width, NUMBER height) long SDLSCREEN = SDL_SetVideoMode(width, height, SDL_DEPTH, SDL_HWSURFACE|SDL_SWSURFACE) SDLWINSIZE.w = width SDLWINSIZE.h = height RETURN SDLSCREEN END FUNCTION
' Closes SDL SUB CLOSEWINDOW() SDL_Quit() END SUB
' Build color FUNCTION SETCOLOR(NUMBER red, NUMBER green, NUMBER blue) uint32_t RETURN (blue + 256*(green + 256*red)) END FUNCTION
' Plots a point FUNCTION PLOTPOINT(NUMBER x, NUMBER y, NUMBER color) NUMBER SDLRECT.x = x SDLRECT.y = y SDLRECT.w = 1 SDLRECT.h = 1 RETURN SDL_FillRect(SDLSCREEN, ADDRESS(SDLRECT), color) END FUNCTION
' Plots a rectangle FUNCTION PLOTRECT(NUMBER x, NUMBER y, NUMBER w, NUMBER h, NUMBER color) NUMBER SDLRECT.x = x SDLRECT.y = y SDLRECT.w = w SDLRECT.h = h RETURN SDL_FillRect(SDLSCREEN, ADDRESS(SDLRECT), color) END FUNCTION
' Clears window FUNCTION CLEARWINDOW() NUMBER RETURN PLOTRECT(0, 0, SDLWINSIZE.w, SDLWINSIZE.h, 0) END FUNCTION
' Draws a straight line FUNCTION PLOTLINE(NUMBER x1, NUMBER y1, NUMBER x2, NUMBER y2, NUMBER color) NUMBER LOCAL dx, dy, i TYPE NUMBER LOCAL dist, stepx, stepy TYPE FLOATING dx = x2-x1 dy = y2-y1 dist = SQR(dx*dx + dy*dy) stepx = dx/dist stepy = dy/dist FOR i = 1 TO dist PLOTPOINT(x1 + stepx*i, y1 + stepy*i, color) NEXT
RETURN 0 END FUNCTION
DEF FN WINDOWUPDATE() = SDL_Flip(SDLSCREEN)
Example file:
INCLUDE "SDLgraphic.bac"
' Window size xsize = 300 ysize = 400
screen = MAKEWINDOW(xsize, ysize)
CLEARWINDOW()
count = 0
REPEAT red = RANDOM(256) green = RANDOM(256) blue = RANDOM(256) color = SETCOLOR(red, green, blue)
width = RANDOM(xsize) height = RANDOM(ysize)
xstart = RANDOM(xsize) ystart = RANDOM(ysize)
PLOTRECT(xstart, ystart, width, height, color)
WINDOWUPDATE()
' Only works if a consolle is open and focused key = WAIT(0, 50)
INCR count UNTIL key != 0 OR count = 100
CLOSEWINDOW()
END
However, I don't know how to get keyboard or mouse inputs. Don't know how to access SDL structures for that and standard BACON functions like WAIT only seems to work if a console is open and focused, not the graphic window.
|
|
l18l
New Member
Posts: 44
|
Post by l18l on May 31, 2011 14:52:50 GMT 1
I think that a true BASIC needs an easy access to graphics, to allow hobby programmers like me to play around. ... Yes, I think that HUG can do it. Here is what I have found. ' Test for graphics without SDL ' 2011-05-30 L18L
INCLUDE "/usr/share/BaCon/hug_imports.bac" INIT
xsize = 300 ysize = 400 count = 0
xsize = 300 ysize = 400 count = 0 win = WINDOW("graf test", xsize, ysize + 30)
key = BUTTON("continue", 100, 30) ATTACH(win, key, xsize - 100, ysize + 1) CALLBACK(key, incr_count)
quit = STOCK("gtk-quit", 100, 30) ATTACH(win, quit, 0, ysize + 1) CALLBACK(quit, QUIT)
can = CANVAS(xsize,ysize) ATTACH(win,can, 0,0) SHOW(can)
SUB draw_random_square
LOCAL red, green, blue LOCAL color$ red = RANDOM(256) green = RANDOM(256) blue = RANDOM(256) color$ = CONCAT$("#", HEX$(red), HEX$(green), HEX$(blue)) SQUARE( color$, 1 + count, 1 + count, xsize/2 + count, ysize/2 + count, 0)
END SUB
SUB incr_count INCR count draw_random_square REM PRINT count," "; END SUB
draw_random_square
DISPLAY
And don't forget there must be an empty last line
|
|
l18l
New Member
Posts: 44
|
Post by l18l on May 31, 2011 15:02:21 GMT 1
Just the colors are RANDOM now
|
|
|
Post by Pjot on May 31, 2011 15:55:08 GMT 1
Thanks FFweb, Indeed l18l is right, it can be done in HUG also. This is a similar version using a selective INCLUDE and keeping as close to your program as possible: IINCLUDE "hug.bac", INIT, WINDOW, CANVAS, SQUARE, TIMEOUT, DISPLAY, DRAW, ATTACH, HUGOPTIONS, KEY, QUIT
INIT
HUGOPTIONS("NOSCALING")
' Window size xsize = 300 ysize = 400
screen = WINDOW("", xsize, ysize)
canvas = CANVAS(xsize, ysize) ATTACH(screen, canvas, 0, 0)
FUNCTION Draw_Square
red$ = HEX$(RANDOM(256)) green$ = HEX$(RANDOM(256)) blue$ = HEX$(RANDOM(256))
width = RANDOM(xsize) height = RANDOM(ysize)
xstart = RANDOM(xsize) ystart = RANDOM(ysize)
SQUARE(CONCAT$("#", red$, green$, blue$), xstart, ystart, width, height, TRUE)
IF KEY() THEN QUIT RETURN TRUE
END FUNCTION
TIMEOUT(50, Draw_Square) DISPLAY
As you can see, the input from the keyboard works here. This is not necessary at all, unless you use an older BASH version Regards Peter
|
|
|
Post by Pjot on May 31, 2011 16:12:21 GMT 1
Sorry ffweb, forgot to answer your question: Indeed it is hard, if not impossible, to access SDL structures. Because of the way SDL is implemented it is very hard to get hold on the relevant information, as SDL keeps everything in a 'C-struct' and uses its members to store information. For WAIT or GETKEY you are right, a console is needed. So if it only is about having drawing facilities to play around with, probably HUG would be a good alternative...? Best regards Peter
|
|
ffweb
New Member
Posts: 20
|
Post by ffweb on Jun 1, 2011 22:11:26 GMT 1
Hi Pjot and l18l
You're right. I find HUG (i.e. GTK) canvas perfect for simple drawing, but a little slow. As an example, when you write a fractal drawing code, you calculate the colors of the pixels one after the other and then you plot them. I wrote this small code to try to test the speed of just filling an area a pixel at a time:
INCLUDE "hug.bac", INIT, WINDOW, CANVAS, PIXEL, TIMEOUT, DISPLAY, DRAW, ATTACH, HUGOPTIONS, KEY, QUIT
INIT
'Window size CONST x_win = 900 CONST y_win = 650 CONST x_size = 800 CONST y_size = 600
timer = NOW DECLARE pixelpersec TYPE double
FUNCTION draw_screen 'Main drawing function LOCAL xp = 0 LOCAL yp = 0 LOCAL go_on = 1
WHILE (yp < y_size) AND (go_on IS 1) IF xp >= x_size THEN xp = 0 yp = yp + 1 IF (KEY() IS ASC(" ")) THEN go_on = 0 END IF 'SQUARE("#111111", xp, yp, 1, 1, TRUE) PIXEL("#111111", xp, yp) xp = xp + 1 WEND
etime = NOW - timer numpixels = yp * x_size + xp pixelpersec = numpixels / etime
PRINT "Elapsed time (s):", etime PRINT "Pixels: ", numpixels PRINT "Pixels per second:", pixelpersec
RETURN TRUE END FUNCTION
win = WINDOW("Test graphic speed", x_win, y_win)
canvas = CANVAS(x_size, y_size) ATTACH(win, canvas, 0, 0)
draw_screen
'Probably useless... DISPLAY
On my old PC, it takes several minutes. But maybe I'd better use Open-GL for this kind of thinks...
Thank you very much for your prompt support!
|
|
|
Post by Pjot on Jun 1, 2011 23:55:45 GMT 1
Well, on the TODO list in the back of my head it is mentioned that I should port the HUG API to an OpenGL backend. Those drawing functions can be ported easily, but problem is of course porting the standard widgets like button, entry, spinbox and so on. There is a thing called MUI which appears to be part of the original GLUT from Mark Kilgard. Some demo programs here. This MUI API is not available in FreeGLUT though, which ships with a lot of Linux distributions because of its liberal license. Besides, the MUI widgets block some of the default GLUT signals. So I cannot port HUG to OpenGL completely. Maybe I should simply restrict myself to a subset of HUG; the window, callback, display and drawing functions could suffice? Any ideas? Regards Peter
|
|
|
Post by Pjot on Jun 2, 2011 19:21:48 GMT 1
Another approach is to use a GL drawing area just for the canvas. There are projects like GtkGlExt or GtkGlArea which embed such a widget. Advantage is that the regular widgets do not need to be ported to GL. Probably GtkGlArea is best as it works with GTK2.x also. Then the HUG API would simply get an additional HUGOPTION to define that the drawing area should be a GL canvas instead of the regular canvas. For example: HUGOPTIONS("CANVAS GL") CANVAS(100, 100) ....
This way the HUG API remains the same, but an OpenGL canvas is used, and the drawing performance improves. Of course your system must have the GtkGlArea widget available... Regards Peter
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jun 2, 2011 20:56:57 GMT 1
|
|
|
Post by Pjot on Jun 3, 2011 15:48:27 GMT 1
Preliminary tests with GtkGlArea show that the performance of drawing lines and points is not better at all.
In fact, it is slightly slower, due to the fact that the GLbuffers need to be swapped after every drawing action, to make the results visible.
So when it comes to performance it seems there is no added value of implementing a GLarea for the canvas.
Regards Peter
|
|
ffweb
New Member
Posts: 20
|
Post by ffweb on Jun 4, 2011 16:44:30 GMT 1
OK. So, lesson learned, until now: pure Open-GL when you need performance in graphics.
On the other side, HUG seems ideal when you are up to GUIs and the like, including some graphics.
Thank you for your efforts, Peter, and for all the value you put in Bacon!
|
|
|
Post by Pjot on Jun 5, 2011 14:32:00 GMT 1
Well I am not sure if this is the lesson to be learned here... what I noticed is that swapping the buffers takes the actual time. Both the GTK canvas and the OpenGL canvas are double-buffered. Swapping this buffer after each tiny action, after each painting of a pixel, is the time-consuming factor, and a comparison simply on basis of one drawing action does not make a lot of difference. With OpenGL one can do a lot of drawing actions using a hardware implementation of the GL specs. After the drawing is finished, the buffer is swapped and the result is shown. This hardware implementation is where the actual power of OpenGL comes from. In GTK however, all drawing is software based and eventually, with a complicated 3D drawing for example, this will result into a slower performance. Nevertheless I think it is a cool idea to optionally use a OpenGL canvas for the drawing, so I have implemented this into HUG. To activate it, first specify a HUGOPTION as follows: HUGOPTIONS("CANVAS GL")
After that, simply create a canvas as usual. Of course your system must have the GtkGlArea library available otherwise HUG will fallback to the default GTK canvas. For the drawing actions, LINE, PIXEL, SQUARE and CIRCLE have been ported to OpenGL also. Your earlier program in OpenGL rendering would now look like this: INCLUDE "hug.bac", INIT, WINDOW, CANVAS, SQUARE, TIMEOUT, DISPLAY, DRAW, ATTACH, HUGOPTIONS, KEY, QUIT
INIT
HUGOPTIONS("CANVAS GL")
' Window size xsize = 300 ysize = 400
screen = WINDOW("", xsize, ysize)
canvas = CANVAS(xsize, ysize) ATTACH(screen, canvas, 0, 0)
FUNCTION Draw_Square
red$ = HEX$(RANDOM(256)) green$ = HEX$(RANDOM(256)) blue$ = HEX$(RANDOM(256))
width = RANDOM(xsize) height = RANDOM(ysize)
xstart = RANDOM(xsize) ystart = RANDOM(ysize)
SQUARE(CONCAT$("#", red$, green$, blue$), xstart, ystart, width, height, TRUE)
IF KEY() THEN QUIT
RETURN TRUE
END FUNCTION
TIMEOUT(50, Draw_Square) DISPLAY
Note that the HUG library has undergone a severe revision, there is a special announcement with a complete OpenGL demonstration program here. Best regards Peter EDIT: now HUG has another backend for OpenGL (with GtkGlExt), the above program was modified slightly...
|
|
2lss
Full Member
Posts: 140
|
Post by 2lss on Jun 13, 2011 4:59:00 GMT 1
What about clutter? You can do some cool stuff with it. www.clutter-project.org/I'm not very familiar with opengl so take it as a grain of salt. I did a couple tutorials in bacon awhile back. I could upload them if needed.
|
|
|
Post by Pjot on Jun 13, 2011 18:31:43 GMT 1
Hi 2lss,
Thanks for the link! Never heard of "Clutter" before. Reading through the docs it appears to be a kind of layer between OpenGL and high-level GUI widgets like buttons, text entries and so on. It would allow a GUI completely based on OpenGL (a thing I was wondering about before).
I am not sure if BaCon could handle the whole low-level API of creating classes...?
But maybe Clutter can also be used as backend for the current OpenGL canvas... I'll study it a little bit more.
Thanks again, Peter
|
|
2lss
Full Member
Posts: 140
|
Post by 2lss on Jun 14, 2011 3:48:42 GMT 1
|
|