Author Topic: [BMAX] realtime per pixel manipulations?  (Read 5148 times)

0 Members and 3 Guests are viewing this topic.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Does anyone know if there is a decent way to do per pixel calculations and plot them using Blitzmax?

Currently I can just make pretty patterns and plot them per pixel. This takes about 3 - 4 seconds to fill a 640x480 screen. I would love to see some of my ideas and calculations in real time so I could interpolate between them. Is this sort of calculation reserved for assembly code?
Challenge Trophies Won:

Offline stormbringer

  • Time moves by fast, no second chance
  • Amiga 1200
  • ****
  • Posts: 453
  • Karma: 73
    • View Profile
    • www.retro-remakes.net
Re: [BMAX] realtime per pixel manipulations?
« Reply #1 on: June 29, 2008 »
I'm not using BMAX, but the technique is always the same:

1) avoid any provided GetPixel()/SetPixel() type of functions
2) work in a memoy buffer that has the size of your screen (can be large depending on the resolution you use, color mode, etc)
3) avoid creating your own Get/SetPixel() routines, access the buffer directly, or (if you can) write Get/SetPixels but with an inline qualifier (so the code of the function is expanded where you call it, avoiding an expensive function call)
4) update the screen with your in-memory buffer, once

This is valid for any language/framework, etc.
We once had a passion
It all seemed so right
So young and so eager
No end in sight
But now we are prisoners
In our own hearts
Nothing seems real
It's all torn apart

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [BMAX] realtime per pixel manipulations?
« Reply #2 on: June 29, 2008 »
I did a seach in my code folder and found some code from Jon he wrote a long time ago. It uses glDrawPixels and an array buffer to store the pixels of the screen. Its fairly quick for pixelwise manipulation, so it might be a technique you can use. I am fairly certain that he posted this back on the old forum, so I am thinking that he don't mind me posting it here again. I made a small example of how its used.

Code: [Select]
Global screen:Int[640*480]

Global timer:Int = MilliSecs()
Global FPS_Real:Int = 0
Global FPS_Cnt:Int = 0
Global FPS_Check:Int = MilliSecs()+1000

ptc_open("Test",640,480,0,60)
While Not KeyHit(KEY_ESCAPE)
ptc_update(screen)
FPS_Cnt :+ 1
If MilliSecs() > FPS_Check Then
FPS_Check = MilliSecs()+1000
FPS_Real = FPS_Cnt
FPS_Cnt = 0
End If
If MilliSecs() > timer+50 Then
timer = MilliSecs()
randomStuff(screen)
End If
If KeyHit(KEY_SPACE) Then Print FPS_Real
Wend
ptc_close()

Function randomStuff(screenBuffer:Int[] Var)
For Local y:Int = 0 To 479
Local yoff:Int = y * 640
For Local x:Int = 0 To 639
screenBuffer[yoff+x] = (255 Shr 24)+((x/3) Shl 8)+(y/2)
Next
Next
End Function

'-----------------------------------------------------------------------------------------------------
'
' OpenGL Frame Buffer Lib By Joncom2000 of The Tin Dragons
'
' Based on code by Jim Shaw & Rbaz, Inspired by TinyPTC by Gaffer.
'
'-----------------------------------------------------------------------------------------------------
'----------------------------------------------------------------------------------------------
' Globals used by the lib to store screen size
'----------------------------------------------------------------------------------------------
Global g_w:Int
Global g_h:Int
'-----------------------------------------------------------------------------------------------------
' Place Functions after this
'-----------------------------------------------------------------------------------------------------
'------------------------------------------------------------------------
' NAME : ptc_open()
' PURPOSE : This function opens the display
' INPUTS : Title, width and height for screen Also hertz
' RETURNS : nothing
' NOTES : N/A
'------------------------------------------------------------------------
Function ptc_open(Title$,width=640,height=480,Depth=32,Hertz=60)
'Set globals
g_w=width
g_h=height
'open screen
GLGraphics(g_w,g_h,Depth,Hertz,GRAPHICS_BACKBUFFER)
AppTitle$=Title$
glViewport(0, 0, g_w,g_h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0,g_w,g_h,0,0,1)
glPixelZoom(1,-1)
glRasterPos2i(0,0)
End Function
'------------------------------------------------------------------------
' NAME : ptc_update()
' PURPOSE : This function updates the display
' INPUTS : pixel buffer pointer
' RETURNS : nothing
' NOTES : N/A
'------------------------------------------------------------------------
Function ptc_update(pBuffer:Byte Ptr)
glDrawPixels(g_w,g_h,GL_BGRA_EXT,GL_UNSIGNED_BYTE,pBuffer)
Flip False
End Function
'------------------------------------------------------------------------
' NAME : ptc_close()
' PURPOSE : This function closes the display
' INPUTS : none
' RETURNS : update
' NOTES : N/A
'------------------------------------------------------------------------
Function ptc_close()
' Doesnt seem needed but I might add cleanup code at some point if needed
End Function

Offline stormbringer

  • Time moves by fast, no second chance
  • Amiga 1200
  • ****
  • Posts: 453
  • Karma: 73
    • View Profile
    • www.retro-remakes.net
Re: [BMAX] realtime per pixel manipulations?
« Reply #3 on: June 29, 2008 »
if you are using OpenGL to update your screen, then avoid glDrawPixels (if you are looking for performance).

Instead:

1) create a texture (GL_TEXTURE_2D is supported by all the graphic cards) with RGBA 8bit color mode (internal mode) => this will give you the best perf.
2) do your stuff in your memory buffer
3) update the texture using glTexImage2D()

This is the fasted way. Of course use GL_UNSIGNED_BYTE for your storage data type. Unless you want higher precision (which is useless if it's for a game/demo)

It may sound stupid to use a RGBA color mode if you do not need the alpha channel (transparency). But actually this is much faster on some machines since the size of the data to be transfered is a multiple of 4 bytes then. This increases the speed as the data moving is much faster than sizes that are multiple of 3... makes sense for a computer ;)
We once had a passion
It all seemed so right
So young and so eager
No end in sight
But now we are prisoners
In our own hearts
Nothing seems real
It's all torn apart

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1389
  • Karma: 84
    • View Profile
Re: [BMAX] realtime per pixel manipulations?
« Reply #4 on: June 29, 2008 »
Thanks for the help! I'll have a crack at it later when I get a chance.
Challenge Trophies Won:

Offline stormbringer

  • Time moves by fast, no second chance
  • Amiga 1200
  • ****
  • Posts: 453
  • Karma: 73
    • View Profile
    • www.retro-remakes.net
Re: [BMAX] realtime per pixel manipulations?
« Reply #5 on: July 01, 2008 »
On my way back home I've been thinking about your question here... weird, isn't it?

anyway... I did not check your code so I cannot appreciate your skills yet, but if you are looking to improve the speed of your algorithms, here are a couple of things to bear in mind as well:

1) clipping! Get/SetPixel() functions usually have clipping tests (4 tests). That's way too much for RT applications unless you are only plotting a small number of pixels. Have a look at your algoritm and perform clipping at the higher levels, i.e. before plotting your pixels.

2) reverse mapping! depending on what you want to draw/paint/etc, you may consider reverse mapping. This means that instead of computing the destination x & y coordinates, you go from the destination <x;y> coordinates to the <u;v> source coordinates (e.g. texture mapping). This works as long as your function can be reverted.

This can be difficult sometimes (e.g. implicit surfaces), so consider an approximation through a triangle-based mesh, then simply render the triangles. This is very handy for any warping/morphing/distortion type of effect.

Have fun!
We once had a passion
It all seemed so right
So young and so eager
No end in sight
But now we are prisoners
In our own hearts
Nothing seems real
It's all torn apart

Offline Sledge

  • C= 64
  • **
  • Posts: 49
  • Karma: 12
    • View Profile
Re: [BMAX] realtime per pixel manipulations?
« Reply #6 on: August 03, 2008 »
PixmapPixelPtr() seemingly has its uses here.
Challenge Trophies Won:

Offline TinDragon

  • Pentium
  • *****
  • Posts: 644
  • Karma: 24
    • View Profile
    • J2K's blog
Re: [BMAX] realtime per pixel manipulations?
« Reply #7 on: August 05, 2008 »
I dont know how good the proformance of that pixelmap command is but I can say that the ptc style lib works well at throwing the pixels to the screen, gldrawpixels may not be the fastest method but to be honest doing pixelwise stuff above 640*480 res is going to be slow however you do it as you have to throw something from ram to the graphics card, its why everyone started moving to opengl and directx for demos in the first place, the processor is no longer tied up doing your 3d maths the gfx card does it so you can do more stuff with the free cpu but were talking about oldskool style stuff more than HDR/Bloom and all that other fluff :D

One other thing I will say about doing pixel stuff in bmax, some commands seem dead slow compaired to some other languages and even versions of blitz, when I was coding some demo tests for the ptc clone lib I noticed that rnd or rand were slow as hell, so avoid doing calls to this in any loops as much as possible and were you can pre-calc values that follow a pattern, not saying you need to do this for things like sin/cos more very complex maths, of course that does remove in some cases the realtime nature of the thing but compromise is better than slideshow  ;)