News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

PlayBasic2DLL Questions?

Started by ScottieB, August 13, 2016, 05:37:35 AM

Previous topic - Next topic

ScottieB

Dear Kevin,

I recently purchased PlayBasic2DLL and it's new to me.
I was wondering if you could refur me to all articles that are about it.  I found a few just not sure if it's all the info I could see about the subject.
Also could you please post a beginners tutorial for the operation of this tool.  I would love to know how to operate it and use it to my behave.
The basics would be great for a start then maybe I can move on to the more complicated topics.
Thanks
ScottieB

Well,  Today I read a few articles to get me started they were very informative.

I have some questions though.  I bought this program because I wanted mainly to increase graphics performance.
The slight drawback so far is I don't know much about poking and peeking within video memory or image memory.
I wanted to know if you could teach me a bit about it?  I would love to to have very fast plotting and reading of pixels so I can do some more fancy graphic demos.
Even a fast screen fade would produce a red alert demo.  While fast plotting could be screen desovles.  Not to mention alot more.
fast reading could increase speeds of raycasters ect...  If you could cover how so basic drawing routines could be optimized many new thing could be more possiable.
please this is why i purchased it in the first place.  any help would be greatly appriciated.
Big Thanks
ScottieB

kevin

#1
    The package comes with html documentation,  it's not brilliant, but it does include a getting started section and bunch of info on stuff like raw pixel writing (Although you can find that in the PB manual).   However,  since PB2DLL is an extension package,  it assumes the user knows their way around PlayBASIC fairly well.  

    To a build a DLL from PlayBASIC source,  you first write the library code as normal.  When it's complete tested and ready to deploy.   Then you fire up PB2DLL, then compile the source into a DLL.  It's pretty much one step process.   The tool creates a DLL and a playbasic (PBA) source file that has the DLL's bindings in for you.   So use the library in your code you copy those files to you project and #incllude the source and you're way.  
 
     A PlayBASIC library is simply a source file (PBA extension) with a collection of PlayBASIC functions in it.  The functions can have set up code, but it should not contain a 'main' loop like a normal program.    The main point is that your library code should compile on it's own, away from your project.    So there can't be any dependencies and a programmer could just #include at the top of  any program and start using the functions.



PlayBASIC Code: [Select]
// --------------[MAIN.PBA] -------------------------------------------

//
#include "MY-LIBRARY.PBA"

TestImage=DLL_MakeColouredImage(256,100,$00ff00,2)


drawImage testimage,100,100,False

Sync
waitkey




// --------------[MY-LIBRARY.PBA] -------------------------------------------

// To build a DLL you first write your library. When it'd complete
// tested and ready to deploy.


// Exported DLL functions need to prefixed with DLL_ These are functions
// that will be visible from outside of the function. So everything
// else will be private and invisible the user of the library.





// Example
Function DLL_AddIntegers(A,B)
Result=A+B
EndFunction Result



// Make colour image. using direct memory access.

Function DLL_MakeColouredImage(Width,height,Colour,Format)

if Width>0 and Height>0
ThisImage= newImage(Width,Height,Format)


OldSurface=GetSurface()

rendertoimage ThisIMAGE

ThisRGB=Point(0,0)

Depth=getImageDepth(ThisIMAGE)


Lockbuffer

; read a pixel to make sure the GFX engine is pointing at this
; surface, it's possible it may not be after a LOCK
ThisRGB= Point(0,0)


ImagePointer = GetimagePTR(ThisIMAGE)

; Get the number of pixels that make up 1 row of pixels in this image
; different colour formats mean the row width will differ. It's best
; to never you know the pitch/modulo of the surface.. Always query it
ImagePitch = GetimagePitch(ThisIMAGE)



Select Depth


// ---------------------------------------------
case 32
// ---------------------------------------------

For YLP =0 to Height-1

// Compute address in memory of this row of 32bit pixels
RowAddress = ImagePointer + (YLP* ImagePitch)
For XLP =0 to width-1
PokeInt RowAddress, COLOUR
// Move to the next pixel across the row
RowAddress+=4
next
next


endselect

unlockbuffer



rendertoimage OldSurface

endif

EndFunction ThisIMage









     The above mock up,  shows how to manually address pixels in a 32bit image.   For understanding how images work, this isn't a DB2DLL thing, it's a PlayBASIC thing.  There's many many example of here and in the documentation.   Here's one from 2009 PlayBasic Optimization Tutorial  - Cross fade Methods which goes through a few cross fading ideas.



 Related Links:

         * 2D Shapes - Making a library for PlayBASIC2DLL (2021-01-15)

        * PlayBASIC To DLL (Development Blog)

        * Tutorial - A Crash Course In BASIC program Optimization  


         

ScottieB

#2
Thanks Kevin that's a big help.
Is there also a way to read pixels fast?  (PeekInt)???
You said that image writing is mostly a playbasic thing not a playbasic2dll thing so where else can I look to learn more about this?
I not finding many examples only a few but I'll keep searching anyways.
Any more information you can give me would be nice even if its how fast can we clear the screen with a color consecatively.

This sounds like I need to learn to look into image addressing peeking and pokeing within image memory at proper addresses.
I've never gone that deep with image manipulation.  It also sounds like I need to know about image structure and how that is comprised as
I don't think I want to get it fouled up when messing with memory addressing?  
Can you give a good explanation to what is going on here? and how the bytes are arranged?  A good run down on the structure of this would be nice.
This looks to be a advanced topic not for anyone that does not use playbasic alot.

What I sort of get right now is where looking a pointers that show use the starting memory address and work from there byte wise either looking or putting our new
correct bytes directly into image memory.  I'm just not sure how to do this correctly without not knowing about proper structure on what this constists off.
And I'm quite sure I don't want to get it wrong so good understanding is a must or it could potentallly hurt program or maybe computer.

So...
Is there a way you could explain this well in simple and consise words without being overly diffucult???

Also...

It seems as though we need to know hexcodes for colour information and what about about floodfills of sreen or even arrays when were dealing with search algorytms??
I gueess this kind of stuff also could relate to memory addresses within arrays correct???  Optimaztions like this could really boost playbasic program proformance. So...
I queess I like to know how this protains to arrays as well?? exspeciallly if A.I.  Algos parents and childs nodes could be executed faster.

After searching around a bit I came up with these by you.

ScreenWidth      =640
ScreenHeight   =400

openscreen ScreenWidth,ScreenHeight,32,1


Dim Ptr as pointer

if GetScreenDepth()=32
   Lockbuffer
   Ptr =getimageptr(0)
   Pitch =getimagepitch(0)
   Depth =getimagedepth(0)

      For ylp=0 to ScreenHeight-1
         Dim LinePtr as integer pointer
         LinePtr =Ptr+Ylp*Pitch
         For xlp=0 to ScreenWidth-1
            *LinePtr=rgb(ylp,xlp*ylp,xlp)   
            LinePtr=LInePtr+1
         next
      next
   UnLockbuffer
endif
print int(ptr)
print Pitch
print depth

sync
waitkey

and... *********

openscreen 800,600,32,1
lockbuffer
   Address   =getImageptr(0)
   Picth      =GetIMagePitch(0)
   Depth   =GetIMageDepth(0)

   if DEpth=32
      for x=0 to GetSurfacewidth()-1
         PokeInt Address+(x*4),rndrgb()
      next      
   
      
   endif
unlockbuffer

Sync
waitkey


This looks too be sort of what I'm looking for but also with reading and colour capiablities.
Any suggestions since these are old posts????

A few examples would also be super great.
Thanks
ScottieB

kevin

#3
  An image is just a 2D array of colours, stored Width by Height.  The number of bytes per colour can range from 2 bytes per pixel (in 15 or 16 bit modes), to 3 bytes for 24bit and 4 bytes for 32bit.    


 Here's some quick links,  

    * PB2DLL - Water Demo
   * Sinus Example
   * Image data file save-load
   * Low Level Pixel Manipulation Example
   * Screen/Image Direct Memory Access
   * Encode File  / Hide File Contents / Xor Encryption
   * Async Flood Filling & Flood Filling Optimizations Example


    Here's an image from the GetImagePtr there's nothing more to it.  

PlayBASIC Code: [Select]
  Cls RGB(0,0,255)

; create four images in each in a different video format
w=128
h=256
CreateFXImageEx 1,w,h,15 ; 15bit version
CreateFXImageEx 2,w,h,16 ; 16bit version
CreateFXImageEx 3,w,h,24 ; 24bit version
CreateFXImageEx 4,w,h,32 ; 32bit version



; Draw them to the screen
Xpos=60
Ypos=50
For i=1 To 4
FillImage(i)
Text Xpos,Ypos, "Address:"+Str$(GetImagePtr(i))
Text Xpos,Ypos+20," Pitch:"+Str$(GetImagePitch(i))
Text Xpos,Ypos+40," Depth:"+Str$(GetImageDepth(i))

DrawImage i,Xpos,Ypos+60,false
Xpos=Xpos+w+40
Next


; show the screen and wait for user to press a key
Sync
WaitKey





Function FillImage(ThisImage)

RenderToImage ThisImage

LockBuffer

Address =GetImagePtr(ThisImage)
Pitch =GetImagePitch(ThisIMage)
Depth =GetImageDepth(ThisImage)

Colour=0
For ylp=0 To GetImageHeight(ThisImage)-1
Colour2=colour
For xlp=0 To GetImageWidth(ThisImage)-1
PokePixel(Address,Pitch,Depth,Xlp,Ylp,Colour2)
Colour2=Colour2+1
Next
Colour=RgbAlphaAdd(Colour,$020101)
Next
UnLockBuffer
RenderToScreen

EndFunction


;*=------------------------------------------------------=*
; >> Generic Poke Pixel Routine <<
;*=-----------------------------------------------------=*

Psub PokePixel(Address,Pitch,Depth,Xpos,Ypos,Colour)
If Address<>0
Select Depth
Case 15 ; 16bit RGB 555 format

R=LSL16((RgbR(colour) & $f8),7)
G=LSL16((RgbG(colour) & $f8),2)
B=LSR16((RgbB(colour) & $f8),3)
pokeword Address+(ypos*pitch)+(xpos*2), R | G | B

Case 16
R=LSL16((RgbR(colour) & $f8),8)
G=LSL16((RgbG(colour) & $fc),3)
B=LSR16((RgbB(colour) & $f8),3)
pokeword Address+(ypos*pitch)+(xpos*2), R | G | B


Case 24 ; 24bit RGB's
R=RgbR(colour)
G=RgbG(colour)
B=RgbB(colour)

Address=Address+(Ypos*pitch)+(xpos*3)
pokebyte Address,R
pokebyte Address+1,G
pokebyte Address+2,B

Case 32 ; 32bit RGB either XRGB (-888) format or (ARGB 8888) format
pokeint Address+(Ypos*Pitch)+(Xpos*4),COlour

EndSelect
EndIf
EndPsub







ScottieB

Most imformative,
Thanks for all the help.
I'll study these over.
Any ideas on how we handle a grayscale image / 256 coloured images (0-255) like in a heightmap?
I found this very interesting.  I'll have to try some testing.

kevin


gray scale's are just normal images.  In an 8bit one you just take either the R,G or B from the point and use it as height.  in 16bit versions you'd take G,B  as the height.


ScottieB

#6
Been trying out lots of different things.
I finally figured out some new stuff.
Hey,  I'm having trouble with FastDot And FastPoint on Images.
I Got Screen O.K. but whats the proper way on an image?  Is There a difference with FX Images?  And Yes,  I had to seed them.


This morning I got FastPoint And FastDot with images using NewImage and CreateImage still not sure about FX And AFX though?
I also was looking at your palette mapping library where can I get more info?  Like whats the commands in the include?
Will palettemapping make me palettes with a whole range like a fire palette with gradients from like say white to yellow to orange to red to black blending as it goes or
is that another command for makeing palettes?  I deffinately see your doing palette rotation!

kevin

  The screen is image 0, so there's no difference in between and image and screen.   All you do Render to the surface,  lock it,  mod it , unlock it..   Actually  my previous post shows exactly how to this.  You find lots of examples using LockBuffer,   Just search for the forums.

The palette mapping commands are all listed in the help..

Palette Mapped Example


ScottieB

#8
Yes, I can read/write fastdot and fastpoint to images but crashing when I do FXImage AFXImage any ideas?
I guess thats difference between video memory and computer memory but is there still a way?
FX And AFX are usually faster too.

kevin

#9
Quote
Yes, I can read/write fastdot and fastpoint to images but crashing when I do FXImage AFXImage any ideas?

 No, that's not normal.  The example in these thread is reading/write to FX images.      So why not post your code ?


PlayBASIC Code: [Select]
      ThisImage = NewImage(200,200,2)


rendertoimage ThisImage
lockbuffer
ThisRGB=Point(0,0)
for ylp=0 to GetImageHeight(ThisImage)-1
for xlp=0 to GetImageWidth(ThisImage)-1
ThisCOLOUR = rgb(YLP,0,XLP)
FastDot xlp,ylp, ThisCOLOUR
next
next
unlockbuffer

rendertoscreen

drawimage ThisImage , 200,200,false



Sync
waitkey








Quote
FX And AFX are usually faster too.

please read the images tutorial in the help.  Go to Help -> About -> Images  




ScottieB

I guess your right.
I must of been messing something up or I was a bit confused.
Thanks for the clearification.
These have been the start of some really cool speedups.
I learned a bunch of commands in the process.
Thanks!
That will make for better programs.

Do you feel like getting into arrays and how these can also be accessed differently much like we used poke and peek on video and images?
Some speedup for arrays persay?  LIke in the playbasic2dll they start to mention it but can you put it alittle better or clearify?
Thanks Again
ScottieB

kevin


  All this stuff is there covered in the PlayBASIC manual.  See  Help->Memory Management -> GetArrayPtr in the help files for search for in the examples packs and here on the forums.

  none the less, here's cut'n'paste from the help..  as for where and what you'd use direct access is up the programmer.    It appears in lots of my examples, so my suggestion would be study them.


PlayBASIC Code: [Select]
; =============
; Part #1
; =============

; Create an Array Called Table()
Dim Table(10)

; Store values in this array
For lp=0 To 10
Table(lp)=100+lp
Next


; =============
; Part #2
; =============


; Get the Base Address of this array
Address=GetArrayPtr(table())

; peek the array memory and show the elements
ShowArray(Address)

; manually poke some new values into this arrays memory
Print "Poking Data Directly Into This Arrays Memory"
DataAddress=Address+pbarraystruct_size
For lp=0 To 10
pokeint Dataaddress+(lp*4),2000+lp
Next

;Show the array memory again
ShowArray(Address)

Sync
WaitKey

Function ShowArray(Address)
Print "Display Array Data"
DataAddress=Address+pbarraystruct_size
For lp=0 To 10
Print peekint(Dataaddress+(lp*4))
Next
EndFunction


ScottieB

#12
Here's a look at what I'm now trying to make FastDot And FastPoint Do.

It's quite the speed up from older commands.
It's even faster with shorter ray lenghts.
It's not done but I'm experimenting.

First I need hieght values for scaled columns.
Then I need Colour values from colour map.
I'm going to get rid of fisheye distortion caused by spherical projection its a distance correction.
I haven't worked out the final projection but it's a start with many a read.
Any ideas how to make it faster so far?  Or what is the best commnads (Fastest!) to use to draw scaled columns?

Obviously,  The third loop so far will be different since that will be the final display.
but the question is can the first two loops be reduced to one!  or get rid of the redundency of the loops?
It would be nice to know right from the start if there's a better approuch for faster rendering times.



Thanks
ScottieB

kevin

#13
  The fastDot/FastPoint commands are about a decade old now :)

 yeah...I don't know why there's 2 loops doing the same thing, so one would be better, or why there's cos/sin computations insides the loops...  so a more optimal version of the loop would be,


PlayBASIC Code: [Select]
   For Rays = 0 To X_Screen_Res

ca#=Cos(Player_Angle + FOV_Angle#)
sa#=Sin(Player_Angle + FOV_Angle#)

For Lenght_Of_Ray = 0 To Maximum_Lenght_Of_Ray
X_Player_Eye = X_Player + ca# * Lenght_Of_Ray
Y_Player_Eye = Y_Player - sa# * Lenght_Of_Ray
Colour = FastPoint(X_Player_Eye,Y_Player_Eye)
Voxel_Height(Lenght_Of_Ray , Rays) = Colour
Next Lenght_Of_Ray

FOV_Angle# = FOV_Angle# - Increment_FOV_Angle#

Next Rays





     If you move Cos / Sin out the inner loop, that's at least 4 instructions per pixel that dont need to be calculated.  

    You can get rid of the point and array read / writing completely..   It worth noting that CPU's don't like reading from large 2d arrays,  so it can be more optimal to use tiles.  
 
    Anyway,  for production code what most coders do is they unroll the inner loop calculations out to the simplest form possible.   Normally a 4 or 8 to 1 ratio is most effective.  So 4to1 means 1 loop for every 4 pixels..  

PlayBASIC Code: [Select]
   Size = 50000


Do
cls 0


frames++

t=timer()

// mock up brute force loop inter

For lp=0 to Size
x=x+speedX
y=y+speedY
next
tt1#+=timer()-t

print tt1#/frames


// mock up unrolled loop



t=timer()

// mock up unrolled loop
X1 = X+SpeedX1
X2 = X1+SpeedX1
X3 = X2+SpeedX1
X4 = X3+SpeedX1

Y1 = Y+SpeedX1
Y2 = Y1+SpeedX1
Y3 = Y2+SpeedX1
Y4 = Y3+SpeedX1

SpeedXBy4 = SpeedX*4
SpeedYBy4 = SpeedY*4

For lp=0 to (Size/4)-1

; pixel 1
x1=x1+speedXby4
y1=y1+speedYby4

; pixel 2
x2=x2+speedXby4
y2=y2+speedYby4

; pixel 3
x3=x3+speedXby4
y3=y3+speedYby4

; pixel 4
x4=x4+speedXby4
y4=y4+speedYby4


next
tt2#+=timer()-t

print tt2#/frames



sync
loop








ScottieB

#14
I get the moveing of sin/cos correctly.
Not understanding the tiles thing though?  I need to store information (arrays) for 3d-projection later.  Did'nt know CPU's didn't like this as I thoought most programmers used theses while programming.  But I still would like to understand what tiles are about?  Sounds like a pixel average.  still how's that going to be stored for later use?

Yes, I can get rid of the last loop since it's just for testing purposes and this will be replaced by the 3d-projection but...

Is there a way to make a loop that will do reading/writing from multiple maps? Or do I have to do each one separately? Like my above code I want height values then I want colour values each
from different maps but can this loop be reduced to one and still get both data from both maps?

I could probablyget rid of some arrays if I did'nt have to lock/unlock bufffers but I have to too use fastDot/fastpoint unless I can render elsewhere's as I read/write with them but that again
uses another image/screen that I have to write too.  So How can I approach this where I read/writeing all over the place?