News:

Function Finder  Find all the functions within source code files

Main Menu

G2D - 2D OpenGL library for PlayBASIC (WIP / BLOG / SCRATCH PAD)

Started by kevin, June 24, 2014, 02:08:07 PM

Previous topic - Next topic

kevin




 G2D - 2D OpenGL library for PlayBASIC  (WIP / BLOG / SCRATCH PAD)

 Project Started:  18th, June, 2014

 PlayBASIC version:  For use with PlayBASIC V1.64P (Beta Edition 42 or higher).







What's this thread ?:


          This is the initial development blog for the library.   So in here you'll find all types of stuff covering the libraries early development.   You know all the bare bones  how's and whys stuff, will a good interjection of  screen shots, code snippets and tips.

          NOTE: I really wouldn't expect the code snippets posted in this thread to work with every version of the library.  The command set names are a fluid thing and subject to change at any time.   If you interested in using the library, then read this stuff very carefully !




What is G2D?:


   G2D is an alternative rendering library the uses the OpenGL API rather than the DirectX / Software interface that PlayBASIC normally uses.   The command set is very minimal at this point, in fact only about a dozen primate operations are supported at all.   Those that are, try to be functionality identical to the internal PlayBASIC equivalent command, while only drawing to the OpenGL screen.

   G2D currently only works with PlayBASIC windowed modes, the library attaches the GL viewport to the PlayBASIC  window.  When we do this,  both the DX and GL screens are being to drawn to the same window.   You can get rid of the DX screen using the ScreenLayout command.   The command gives you a rect (X1,y1,x2,y2) of where the DX screen should be drawn within the window.   To get rid of it,  just position it outside of the window.  


    This library was written in PlayBASIC V1.64P and converted to a DLL with PB2DLL :)




G2D FAQ:



   Q. Can I Draw internal PB graphics commands to the GL screen or vice verse ?

                   A.  Nope,  you can't draw between them.  


   Q. Does the Library cache states to optimize draw calls ?

                   A. Nope.   So basically everything we draw is it's own unique draw call.  This is less than optimal, but for now I'm more interested in if it works,  than trying to really optimizing stuff.


VIDEO:


   




DOWNLOADS:


          Get Downloads from the  Download G2D Release Thread (login required)  




kevin

  G2D - Basic Image Support

      Tonight (well this morning it's 5:30AM here) I've been working on getting some basic image commands hooked up.   Since this library is build for use with PB's internal commands, i'm going to try and keep things like images in parallel with each other.  By that i mean when you load a G2D image,  the command loads the pixel data into PlayBASIC (AFX) image at whatever slot you wanted.  Once loaded it then translates this to a format GL understands (a texture).   Rather than kill off the source, It then keeps both versions.    The theory being is we can use PB's internal sprites/collision functions in the background to do pixel based effects.   Haven't test this, but it should work in theory.  


       Anyway bellow here's a look at some test code, there really shouldn't be any surprises for you... If there is, RTFM...


PlayBASIC Code: [Select]
      Explicit True      

TitleScreen "G2D - 2D OpenGL Library Test For PlayBASIC V1.64P"

// First up the open GL library
Dim GL as tMyGL pointer
GL=G2DStart(800,600)

; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,500,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2


g2D_loadImage("media/Brick128by128.bmp",1)
g2D_loadImage("media/OpenGl_500.png",2)

Do

; -------------------------------------------------
; Draw a nice gradient to clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)


x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

// grab a grid of images to the frame buffer
for ylp=0 to 4
for xlp=0 to 4
g2dDrawImage(1,x1+(Xlp*128),y1+(ylp*128),false)
next
next

// draw a transparent GL image to the frame buffer
g2dDrawImage(2,100,100,true)


// SYNC the GL screen
g2dsync()


; -------------------------------------------------
; draw on the Direct X surface at the bottom
; -------------------------------------------------
boxc 0,0,400,100,true,0
text 10,10,"Fps:"+str$(fps())+" Count="+str$(Count)


// call PB SYNC too
sync
loop spacekey()=true


g2dEND()






kevin


    G2D - Expanding the core primitives commands

        Fired up the G2D project this evening and have just playing with adding the odd command. Mainly been thinking about ways to build interfaces with the existing internal command sets.   Things like Sprites / Maps are obvious ones.   Rendering a map isn't too difficult, as at least with those all the blocks exist in the same texture.  Sprites are a problem as GL / D3D prefer to render lots of polygons from the same surface/texture. Swapping textures between polygons all the time is really inefficient.  PB sprites support UV mapping, but I don't recall seeing anybody ever use it..

        One way around the problem would be building a GL sprite layer, but then you lose pixel / vector collisions (without rewriting it all in PB).   For now I think I'll just knock up some glDrawAllSprites / glDrawOrderedSprite commands on the GL side and have them try and cache the texture state where possible.   So if the a bunch of sprites fall within a depth use the same texture that should solve most of the texture changing issues, since that state can be held across consecutive textures.   
 
        For maps, i'll prolly just add a glDrawMap routine.  This would compute the output from the PB Map/level you provide, the only different would be it'd have a texture parameter.   A bit like this,glDrawMap Map,Level,Xpos,Ypos,ImageIndex.    So the GL side would look in it's texture index for the surface and if there's a GL texture for this image it'd use that..     This should mean you can use the map collision / occlusion commands etc on the map data completely asynchronously from the GL rendering. 

        Anyway, will think about it in the morning

kevin

    G2D - g2dDrawAllSprites

     Just dropped in a draw all sprites function into the g2d side,  it's dead simple just wanted to test the basic idea really then worry about jazzing it up if need be later.    So far it works fine even though it's running through the PBVM on the standard test machine (Athlon/6600).  The current version  will draw a 1000 anti aliased (500*248 pixel) GL logos around the 27fps mark with no optimization at all.  Which is a pleasant surprise..    

     The demo code shows we're using the existing PB sprite commands with to manage the sprite scene, then just copying the properties required at the end to the GL using the G2dDrawAllSprites function.   So it's basically the same as regular PlayBASIC. 

    Example code.  

PlayBASIC Code: [Select]
      Explicit True


TitleScreen "G2D - 2D OpenGL Library Test For PlayBASIC V1.64P"

// First up the open GL library
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,500,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp",1)
g2dloadImage("media/OpenGl_500.png",2)


local maxsprites,x#
maxsprites=50

For lp =1 to maxsprites
CReateSprite lp
SpriteImage lp,2
PositionSprite lp,rnd(800),rnd(600)
next



Do

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

; draw a grid of this texture at the mouse coord
g2dGridImage(1,x1,y1,4,4,false)

// draw a transparent image to the frame buffer
g2dDrawImage(2,100,100,true)

// draw the sprite scene
g2DDrawAllSprites()

// move the sprites to the right and clip them to the screen width
for lp=1 to maxsprites
x#=getspritex(lp)+lp*0.123
if x#>800 then x#=-800
PositionspriteX lp,x#
next


// SYNC the GL screen
g2dsync()


; -------------------------------------------------
; draw on the Direct X surface at the bottom
; -------------------------------------------------
boxc 0,0,400,100,true,0
text 10,10,"Fps:"+str$(fps())+" Count="+str$(Count)
text 10,30,Scancode()

// call PB SYNC too
sync
loop spacekey()=true


g2dEND()

flushkeys

print "Yeah"
sync
waitkey




kevin

G2D - Batched Sprite Scenes - DrawRotatedImage

      Been in and out most of the day, even so have been able to drop a few more GL equivalent functions into the library.  Commands that come to mind would be G2dTexturedTri,  G2DTextureQuad,  G2dDrawRotatedIMage as well as some tweaks to sprite scene rendering.  


PlayBASIC Code: [Select]
      Explicit True

TitleScreen "G2D - 2D OpenGL Library Test For PlayBASIC V1.64P"

// First up the open GL library
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,550,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp",1)
g2dloadImage("media/OpenGl_500.png",2)


local maxsprites,x#
maxsprites=100

For lp =1 to maxsprites
CReateSprite lp
SpriteImage lp,2
PositionSprite lp,rnd(800),rnd(600)
next


Do

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

; draw a grid of this texture at the mouse coord
g2dGridImage(1,x1,y1,4,4,false)

// draw a transparent image to the frame buffer
g2dDrawImage(2,100,100,true)

// draw the sprite scene
g2DDrawAllSprites()

// move the sprites to the right and clip them to the screen width
for lp=1 to maxsprites
x#=getspritex(lp)+lp*0.123
if x#>800 then x#=-800
PositionspriteX lp,x#
next

g2dTextureTri(2,100,100,500,50,300,300,1)

g2dTextureQuad(2,400,200,800,200,800,600,400,600,1)
local angle#
g2dDrawRotatedImage(2, x1,y1,Angle#,2.5,2.5,-250,-100,true,$8020AA30)

Angle#=wrapangle(Angle#+1)

// SYNC the GL screen
g2dsync()

; -------------------------------------------------
; draw on the Direct X surface at the bottom
; -------------------------------------------------
boxc 0,0,400,100,true,0
text 10,10,"Fps:"+str$(fps())+" Count="+str$(Count)
text 10,30,Scancode()
;text 10,60,MouseBUtton()
// text 10,60,LineCount

// call PB SYNC too
sync
loop spacekey()=true

g2dEND()

flushkeys

print "Yeah"
sync
waitkey



kevin

   G2D - Sprite Scene Testing

    Had something of a set back yesterday after running into some issues with legacy Sprite commands.  The GetSpriteRect() function was crashing and SpriteInRegion as acting funny.   The GetSpriteRect function grabs the bounding box from a sprite, it's ideal for clipping the sprite to a viewport / manual collisions or for things like map translations.  While the issue turned out to be an easy fix, it did take  some time to track down where the issue was coming from.  It turned out the new command set wrapping didn't seem to support the pointer fields correctly, mean it the value it was expecting to be a pointer was almost anything..  So no great surprise it'd crash.

    The other drama was in the SpriteInRegion function which turns out to be wrapper of the Box collision sprite commands.  Not too sure how long that one's been there, but I'm guessing years.  The fix required a behavior change,  as the old solution used the sprites collision mode internally (see->less code), the new solution only checks the bounding box against the rect the user supplies, returning a true/false if they overlap.   Which is how it was meant to work originally.

    These two things caused issue with G2D, as they're were being used to work out if a sprite is visible and where it's bounding rect falls within the g2dDrawAllSprites() function.   I've left the Rect checking out of the they current build of the library, so it'll will work with V1.64P to a degree, but there will be clipping problems with some rotated sprites.

    Yesterdays build of the g2dDrawAllSprites function supports Rotated sprites, Rotation Handles, Visibility checking, Clipping,  Filtering, Tint Colours (ARGB a=Alpha) as well some texture management.  These give you a pretty good amount of control, more than enough to create some interesting stuff.        


PlayBASIC Code: [Select]
      Explicit True

TitleScreen "G2D - 2D OpenGL Library Test For PlayBASIC V1.64P"

// First up the open GL library
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,600,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp",1)
g2dloadImage("media/OpenGl_500.png",2)


local maxsprites,x#
maxsprites=500

For lp =1 to maxsprites
CReateSprite lp
SpriteImage lp,2
PositionSprite lp,rndrange(-800,1600),rnd(550)

centerspritehandle lp

; SpriteTransparent lp,rnd(100)>50
;
; Spritefilter lp,true
;spritecollisiondebug lp,true
if rnd(100)>50
SpriteDrawMode lp,2
rotatesprite lp,45
endif

SpriteTint lp,(rndrgb()<<8)| rnd(255)
next


local fx=newimage(800,600,2)

local ScreenModeToggle

local FrameRate


; ------------------------------------------------------------------------
Do
; ------------------------------------------------------------------------

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

; draw a grid of this texture at the mouse coord
g2dGridImage(1,x1,y1,4,4,false)

// draw a transparent image to the frame buffer
g2dDrawImage(2,100,100,true)


PositionSprite 1,x1,y1
centerspritehandle 1
turnsprite 1,0.25

// draw the sprite scene
g2DDrawAllSprites()

// move the sprites to the right and clip them to the screen width
for lp=1 to maxsprites
x#=getspritex(lp)+1+(lp and 3)*0.123
if x#>2400 then x#=-1600
PositionspriteX lp,x#

; spin it
turnsprite lp,lp/10.0
next


// SYNC the GL screen
g2dsync()



// SYNC the PB screen /user input etc
sync

if enterkey()
if ScreenModetoggle=0
ScreenLayout 0,0,800,600
else
ScreenLayout 0,300,800,600
endif

ScreenModetoggle=1-ScreenModetoggle
flushkeys
endif

Framerate=fps()

loop spacekey()=true

g2dEND()



flushkeys
ScreenLayout 0,0,800,600

cls

print framerate
sync
waitkey
end



   


kevin


  G2D - DrawOrderedSprite scenes

        The previous implementation only included an emulation of DrawAllSprites, which is fine if you don't rely upon sprite depths for the output.   But since there's a basic framework to work with, adding scene sorting is the next obvious addition, which gives us a way to implement a g2dDrawOrderedSprite  command in the Open GL side.   The command works much the same as the existing one on the PB side, where if you compare the output against each other visually, they're almost identical.   It's just quicker pushing rendering off onto a second device such as a GPU. 
   
         Here's some test scene code that include a toggle between displaying the GL and DX screens and well as toggle between the the different sprite scene rendering.

PlayBASIC Code: [Select]
      Explicit True

TitleScreen "G2D - 2D OpenGL Library Test For PlayBASIC V1.64P"

// First up, we open GL library after the Pb screen has been created,
// since it attaches to the window
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,600,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp" ,1)
g2dloadImage("media/OpenGl_500.png" ,2)
g2dloadImage("media/PlayBasicSig2.png" ,3)


local maxsprites,x#
maxsprites=100


local Z=1000
local s#=5

For lp =1 to maxsprites
CReateSprite lp

if rnd(100)>50
SpriteImage lp,2
PositionSpriteZ lp, 500
else
SpriteImage lp,3
PositionSpriteZ lp, 100
Spritefilter lp,true

endif

PositionSpriteZ lp, z
z--
;rnd(1000)

PositionSprite lp,rndrange(-800,1600),rnd(550)
centerspritehandle lp

ScaleSprite lp,2
s#=s#-0.1

;
;spritecollisiondebug lp,true
SpriteDrawMode lp,2
SpriteTint lp,rndrgb()| $ff000000


next


local fx=newimage(800,600,2)

local ScreenModeToggle

local FrameRate


; ------------------------------------------------------------------------
Do
; ------------------------------------------------------------------------

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

; draw a grid of this texture at the mouse coord
g2dGridImage(1,x1,y1,4,4,false)

// draw a transparent image to the frame buffer
g2dDrawImage(2,100,100,true)

// Draw a box
; g2dBOXC(100,100,50,400,0,$ff00ff00)


PositionSprite 1,x1,y1
centerspritehandle 1
turnsprite 1,0.25

// draw the sprite scene


if functionkeys(1)=false
g2DDrawOrderedSprites()
else
g2DDrawAllSprites()
endif


g2dDrawImage(3,GetScreenWidth()/2-(GetImageWidth(3)/2),GetScreenHeight()-GetImageHeight(3),true)


// move the sprites to the right and clip them to the screen width
for lp=1 to maxsprites
x#=getspritex(lp)+1+(lp and 3)*0.123
if x#>2400 then x#=-1600
PositionspriteX lp,x#

; spin it
turnsprite lp,lp/100.0
next

// SYNC the GL screen
g2dsync()

; -------------------------------------------------
; Depending on the mode, we draw the same scene to an FX window on the DX window
; -------------------------------------------------

if ScreenModetoggle

rendertoimage fx
ShadeBox 0,0,800,600,$304050,$304050,$807050,$807050

; draw a grid of this texture at the mouse coord
GridImage 1,x1,y1,4,4,false

// draw a transparent image to the frame buffer
DrawImage 2,100,100,true



if functionkeys(1)=false
DrawOrderedSprites
else
DrawAllSprites
endif

rendertoscreen
drawimage fx,0,0,false
endif


Login required to view complete source code



  To DO list ?

    There's number of things that would be handy building interfaces too, stuff like Maps / Shapes & Fonts are the main ones really.   The G2D side doesn't need a complete implementation of such command sets, just a way of displaying the contents of them on the GL screen.   

    They all have their own little challenges, but fonts could be a bit problematic.  The most obvious solution is build the text into a mesh and render that to the surface, which should work fine.   There is a slight issue with the resolution of the font, and the size of the texture it uses.  Since the font has to be translated to an image and then a GL texture.   If you map all 256 (2^8) characters into a single texture, where each row is 16 character by 16 rows..  Then as long as character width/heights aren't excessive then this should create a texture that's responsible size.    A character width of 16 pixels would give a texture of 256*256 pixels.   Which is peanuts today, but if the characters are 64*64, then that's a 1024*1024 sized texture.   Which will flat out fail on older machines.   

    The texture size stuff is just one of those things you have to get your mind around really,  some of it I can possible hide away within the implementation later,  but initially I think we'll just get working then worry about ways to make it more flexible.

kevin

    G2D - g2dDrawMap (Solid) Test scene

       So bellow we have a GL version of the DrawMap command.  You set up your map the same as normal, it's recommended you use FX or AFX block graphics.   If you're not running pixel impacts on the map, then you don't really need to put any graphics in them.   The g2dDrawMap command current has an additional texture parameter.    This image / texture should contain the block graphics set out on it in a grid.  Just like the internal loadMapGfx command, the importer maps the tile indexes across then down, starting at index zero.  

      For example, if you had 16 tiles, it's recommended you set them out in a 4 by 4 pattern like this,
     

      [00][01][02][03]
      [04][05][06][07]
      [08][09][10][11]
      [12][13][14][15]


     Always try an avoid block mappings that aren't powers of 2.   So grid of 4*4, 8*8, 16*16, 32*32, 64*64, etc  This is because blocks need to be UV mapped as floats, which can have precision errors in them.   See -> 1/3.0

     The same applies to your  block graphics width and heights.    Your blocks texture should aim to be a power of 2 for the best compatibility.   If it isn't, most drivers will automatically make it a power of 2 (cost you extra memory) or simply fail.  

     Bellow is the test scene code.   The test map builds a level that contains a bunch of copies of the input texture made up of from 32 by 32 size blocks.    Tile zero is the transparent tile so it's removed.

PlayBASIC Code: [Select]
      Explicit True

TitleScreen "G2D - G2DDrawMap Map Test"

// First up, we open GL library after the Pb screen has been created,
// since it attaches to the window
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,600,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp" ,1)
g2dloadImage("media/OpenGl_500.png" ,2)
g2dloadImage("media/PlayBasicSig2.png" ,3)
g2dloadImage("media/skin_g.bmp" ,4)



local maxsprites,x#
maxsprites=200

local Z=2000
local s#=5

For lp =1 to maxsprites

CReateSprite lp

SpriteDrawMode lp,2

PositionSpriteZ lp, z
z-=10

if rnd(100)>50
SpriteImage lp,2
PositionSpriteZ lp, 500

else
SpriteImage lp,3
PositionSpriteZ lp, 100
endif

PositionSprite lp,rndrange(-800,1600),rnd(550)
centerspritehandle lp

SpriteTint lp,rndrgb()| $ff000000

next

local fx=newimage(800,600,2)

local ScreenModeToggle

local FrameRate

local ThisMap=NewMap(10)
CreateMapGFX ThisMap,32,32,64,0,2

Local ThisLevel=NewLEvel(ThisMap,100,32)

local TIle,Xlp,Ylp

Local ThisLevelBLock=NewLEvel(ThisMap,7,7)

Tile=0
for ylp=0 to 7
for xlp=0 to 7
PokeLevelTile ThisMap,ThisLevelBlock,xlp,ylp,TIle and 63
TIle++
next
next

for ylp=0 to 10
for xlp=0 to 10
PasteLevel ThisMap,ThisLEvelBlock,ThisMap,ThisLEvel,xlp*8,ylp*8,1111
next
next


; ------------------------------------------------------------------------
Do
; ------------------------------------------------------------------------

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

; draw a grid of this texture at the mouse coord
g2dGridImage(1,x1,y1,4,4,false)

// draw a transparent image to the frame buffer
g2dDrawImage(2,100,100,true)

// Draw a box

PositionSprite 1,x1,y1
centerspritehandle 1
turnsprite 1,0.25

// draw the sprite scene
if functionkeys(1)=false
g2DDrawOrderedSprites()
else
g2DDrawAllSprites()
endif

g2dDrawMap(ThisMap,ThisLevel,x1,y1,4)
g2dDrawImage(4,0,0,false)

g2dDrawImage(3,GetScreenWidth()/2-(GetImageWidth(3)/2),GetScreenHeight()-GetImageHeight(3),true)


// move the sprites to the right and clip them to the screen width
for lp=1 to maxsprites
x#=getspritex(lp)+1+(lp and 3)*0.123
if x#>2400 then x#=-1600
PositionspriteX lp,x#
; spin it
rotatesprite lp,lp ;lp/100.0
next


// SYNC the GL screen
g2dsync()

; -------------------------------------------------
; draw on the Direct X surface at the bottom
; -------------------------------------------------

// call PB SYNC too
sync

loop spacekey()=true

g2dEND()


Login required to view complete source code



    G2D - Compute Relative Cord From Sprite

        Hadn't noticed it before but there seems to be missing a way to compute a rotated/scaled/centered position from a sprite, so just knocked up a few functions as test.  This would be useful when attaching items to a character.    

        The second picture shows the result of test loop. The loop runs through and computes cords across the sprites width/height which are then translated to the final world position relative to the sprite...    The code just draws a box to highlight the coordinate in the scene


PlayBASIC Code: [Select]
            for ylp=0 to 100 step 20
for xlp=0 to 100 step 10

x1=GetSpriteWidth(1)*(xlp/100.0)
y1=GetSpriteHeight(1)*(ylp/100.0)

X1,y1=ZZZ_ComputeSpriteCord(1,x1,y1)
g2dBoxC(x1-3,y1-3,x1+3,y1+3,1,$ffff0000)

next
next







     G2D - Sprite To Sprite Alignment (Limbs)

         Here's another little handy function, this one lets you position a sprite relative to it's parent sprite, in other words you can create sprite limb structures.

         The third picture is show the GL logo with some legs sticks out it spinning around it.  Each leg has 3 limbs, make the object consume over a 100 sprites.. It's not pretty, but hopefully you get the idea.

PlayBASIC Code: [Select]
            local index =2
local ParentSprite

for xlp=0 to 359 step 10

; -------------------------------------
; Position first sprite in limb
; -------------------------------------

ParentSprite=Index
x1=GetSpriteWidth(1)/2 +(cos(xlp)*180)
y1=GetSpriteHeight(1)/2 +(sin(xlp)*60)

spriteimage index,5
scalespritexy index,1,0.5
spritehandle Index,0,GetSpriteHeight(Index)/-2
AlignSpriteToSprite 1,Index,x1,y1,xlp

positionspritez Index,2

index++
; -------------------------------------
; Position second sprite in limb to the end of the previous limb
; -------------------------------------

spriteimage index,5
scalespritexy index,1,0.5
spritehandle Index,0,GetSpriteHeight(Index)/-2
AlignSpriteToSprite ParentSprite,Index,128,16,30

positionspritez Index,5
ParentSprite=Index

index++
; -------------------------------------
; Position third sprite in limb to the end of the previous limb
; -------------------------------------

spriteimage index,5
scalespritexy index,1,0.5
spritehandle Index,0,GetSpriteHeight(Index)/-2
AlignSpriteToSprite ParentSprite,Index,128,16,30

positionspritez Index,6

index++
next





 


kevin

  G2D - Prototype # 4 Released

       Here's today build og he G2D library, it includes more Sprite/Image and Map commands.  For stuff like maps all we needed is a way to render a map to the GL screen, which is what the g2dDrawMap function does.  The only difference to the internal command (DrawMap) is that the g2D version currently requires a texture index to be passed to it as the block graphics.  (See previous post about how that)  
 
       Command wise, this build includes some new sprite commands such as  AlignSpriteToSprite(parentsprite,limbsprite,limbx,limby,limbangle#) and the x#=GetAlignedSpriteCordX(thissprite,cordx)  (there's also a Y version)  which are used to compute the location of point that's attached to a sprite.  Handy for gun turrets. limbs, particles that sort of thing.  
 
       There's also a few new Image functions such as.  

         MakeAlphaChannel(imageindex,maskcolour)   ; This function builds an Alpha channel for images that use MASK COLOUR based transparency. The image can then be converted to a texture use us in a GL scene.

        g2dConvertToTexture(index)    ; This function creates an FX/AGX image to a GL texture for this image.

       What these functions allow us to do is convert existing image media so that's got and alpha channel, which you need for GL

       
       While updating the test/demo with the dll version I did notice the G2DDrawOrderedSprites function seemed to be broken in this build, not too sure why, the g2dDrawAllSprites is working.  




 G2D - Prototype #4 Released

  Get G2D Prototype #4 (login required)




kevin


G2D - Fonts & Text rendering

      In the previous builds Font/Text rendering is missing, so that's been the order of the today's sessions.     For fonts we need to keep a parallel data on the library side,  much that same images.  For each font we need to build a texture of the character set.    The character set is a 16*16 grid, i've included a debug function to actually draw a fonts character set texture to the GL surface, just so I can verify it.   see-> g2ddrawfontimage(Index,Xpos,Ypos,DrawMode)     

      To load a font we use the g2dLoadFont(FontName$,Index,Size,Style), this function wraps the LoadFont function, so in other words first it loads the font using normal LoadFont on the PB side, then from this, is built the character set image/texture and then stores the data in parallel structure on the GL side.    Be warned, any media you load like this, need to be released using the appropriate g2d Delete function. (G2dDeleteImage, G2dDeleteFOnt etc)   - The G2dLoadFont function behaves almost the same as the standard command, with one key difference, which is the command changes the current font on the GL side for the time being.  Will most like change that to match PB's normal behavior.   To make porting DX based renders to GL easier.     

     The only text rendering commands we have at this time is g2dText(Xpos,Ypos,Message$) which is not at optimal in this version, but gets the jobs done.


     The scene bellow shows the scene rendered to GL (TOP) / DX (Bottom) side by side so i can make check the output is

PlayBASIC Code: [Select]
      Explicit True

TitleScreen "G2D - G2DDrawMap Map Test"

// First up, we open GL library after the Pb screen has been created,
// since it attaches to the window
Dim GL as tMyGL pointer
GL=G2DStart(800,600)


; push the direct X screen to the bottom (almost off the screen)
ScreenLayout 0,300,800,600

//
local lp,lp#,x1,y1,x2,y2,count,c,c1,c2

g2dloadImage("media/Brick128by128.bmp" ,1)
g2dloadImage("media/OpenGl_500.png" ,2)
g2dloadImage("media/PlayBasicSig2.png" ,3)
g2dloadImage("media/skin_g.bmp" ,4)
g2dloadImage("media/block.png" ,5)



; Load the ship image into memory
loadImage "media/ship.bmp",6,8

; build alpha channel from the Mask colour
MakeAlphaChannel(6,argb(0,0,0,0))

; now create a texture from it
g2dConvertToTexture(6)



local maxsprites,x#
maxsprites=110

local Z=2000
local s#=5

For lp =1 to maxsprites

CReateSprite lp

SpriteDrawMode lp,2

PositionSpriteZ lp, z
z-=10

if rnd(100)>50
SpriteImage lp,2
PositionSpriteZ lp, 500

else
SpriteImage lp,3
PositionSpriteZ lp, 100
endif

PositionSprite lp,rndrange(-800,1600),rnd(550)
centerspritehandle lp

; s#=s#-0.1

; spritecollisiondebug lp,true
; spritecollisionmode lp,1

; SpriteTint lp,rndrgb()| $ff000000

next

SpriteImage 1, 2
PositionSpriteZ 1, 1

local fx=newimage(800,600,2)

local ScreenModeToggle

local FrameRate

local ThisMap=NewMap(10)
;CreateMapGFX ThisMap,32,32,64,0,2
loadMapGfx "media/skin_g.bmp",ThisMap,32,32,0,2 ; ,4)

Local ThisLevel=NewLEvel(ThisMap,100,32)

LevelDrawMode ThisMap,ThisLevel, 2
local TIle,Xlp,Ylp
/*
for ylp=0 to GetLevelHeight(ThisMap,ThisLEvel)
for xlp=0 to GetLevelWidth(ThisMap,ThisLEvel)
PokeLevelTile ThisMap,ThisLevel,xlp,ylp,TIle and 63
TIle++
next
next
*/

Local ThisLevelBLock=NewLEvel(ThisMap,7,7)

Tile=0
for ylp=0 to 7
for xlp=0 to 7
PokeLevelTile ThisMap,ThisLevelBlock,xlp,ylp,TIle and 63
TIle++
next
next

for ylp=0 to 10
for xlp=0 to 10
PasteLevel ThisMap,ThisLEvelBlock,ThisMap,ThisLEvel,xlp*8,ylp*8,1111
next
next

local MapScrollX

; SetFPS 60



local FontIMage= g2dLoadFont("veranda",10,48,0)

Local Message$="Hello World Hell World []"

; ------------------------------------------------------------------------
Do
; ------------------------------------------------------------------------

; -------------------------------------------------
; Draw a nice gradient clear the GL screen
; -------------------------------------------------
g2dShadeBox(0,0,800,600,$304050,$304050,$807050,$807050)

x1=g2dMouseX()
y1=g2dMouseY()

local xlp,ylp

g2dDrawMap(ThisMap,ThisLevel,MapScrollX,100,4)
g2dDrawMap(ThisMap,ThisLevel,MapScrollX+2000,100,4)

MapScrollX-=1
If MapScrollX<-1000
MapScrollX+=1000
endif


PositionSprite 1,x1,y1
centerspritehandle 1
turnsprite 1,0.25
Login required to view complete source code


kevin

   G2D - Prototype # 5 Released  - Fonts / Text Rendering

    So here's the latest build of the library, there's some fixed functionality with the g2dDrawOrderedSprite command now working as well as the addition of the Font & Text commands.     The bug in the g2dDrawOrderedSprite command was one of the face palm mistakes that only shows up in the translated machine code version, since the runtime have write allocation protection on every write.

    The offending code looked a bit like this,

PlayBASIC Code: [Select]
   ; some code to run through and transfer the sprites settings to a structure for sorting 
For lp=1 to maxSprites

; check if there's a structure at this position
if Array(lp)
; alloc one
Array(lp) = new MySprite
endif

; write into this structure
Array(lp).x = Xpos
Array(lp).y = Ypos

; etc
next




   The code was meant to alloc a new type if  one wasn't present (if a cell inside an array was zero), but instead it'd only allocated types when it already existed.    So in DLL the cell would be null and boom it'd crash..


     To fix it, the IF statement needed a compare with ZERO, since it's looking for empty cells in the array

PlayBASIC Code: [Select]
   ; some code to run through and transfer the sprites settings to a structure for sorting 
For lp=1 to maxSprites

; check if there's a nothing at this position in the array
if Array(lp)=0
; alloc one
Array(lp) = new MySprite
endif

; write into this structure
Array(lp).x = Xpos
Array(lp).y = Ypos

; etc
next





Fonts

    To load a font for g2d we use the g2dLoadFont(FontName$,Index,Size,Style) function.  This function works much the same the LoadFont in the PB command set,in fact it wraps it.   The only real difference is the g2d version covers the vector system font to a texture for rendering in a GL screen.   The g2dLoadFont currently only supports converting system fonts, so if you loaded a CRF bitmap font, then it'll try and convert the character into a texture which loose all the pixel data.     Not big deal, given nobody even uses then.

    For text rendering commands we've g2dPrint and g2dText,  the only difference to native PB command is they require strings.   Where as Print/Text in PB can handle String/Integer/Float fields.  


 
Download

   G2D - 2D OpenGL library for PlayBASIC V1.64P PROTOTYPE #5 (login required)


kevin

 G2D - Draw Ordered Sprites Extended plus Viewer/Camera Control

     One of the missing components from the G2D library at this point is some way of rendering a 'captured' camera scene to the GL screen.   Most PB programs/games seem to use either all sprites/images for the scene or a sprite/map combination.    Creating your own camera routines are not out of the question, but internally it's managing the draw state for you..  Which is one of those "it just magically happens" things you're better off not knowing about.   The GL side is no different,  the rendering routines have to try and manage the device state the best it can to avoid state changes which slow things down.    

     If you think about most map / sprite scenes you've generally got a background, a tile layer or two and sprites either in front or behind the layers.  The internal camera would clip/sorts all the rects then draws the visible rects using painters, but we can duplicate that behavior fairly easily, by using a adding a MinZ and MaxZ range to a variation of the g2dDRawOrderedSprite command.     The new command is called  g2dDRawOrderedSpriteEx  (Ex is for Extended BTW)  

     
    So to draw a scene of 3 layers (Sprites with Z from 500 to 1000), a map layer, then foreground sprites 0 to 499

PlayBASIC Code: [Select]
            ; draw sprites behind map
g2DDrawOrderedSpritesEx(CameraX,CameraY,500,1000)

; draw checker board map layer
g2dDrawMap(ThisMap,ThisLevel,MapScrollX,100,4)
g2dDrawMap(ThisMap,ThisLevel,MapScrollX+2000,100,4)

; draw sprites in front of map
g2DDrawOrderedSpritesEx(CameraX,CameraY,0,499)




    You'll notice there's camera parameters for the command, which i'm trialing at the moment, they do as you'd expect and allow you view the screen sprite from a relative position in 2d space.    Surely those who've ever messed around with the FX prototypes can probably guess what other little ideas I've got in that regard.


    Anyway, the messy show bellow shows the scene, easy as

kevin

  G2D - Perspective Ordered Sprites Scene Test

        Haven't had much time for any projects the past few days (not that there's any interest anyway), was away at a wedding over the weekend and have been trying to catch up on some news / house work (Mowing) ever since...  

        This morning i've have been tweaking the sprite scene routines to support perspective rendering of the scene.  Which just means the final sprites size is the result of perspective projection between the viewer and the sprite.  Which means sprites closer to the viewer (those with a smaller Z) will be larger than those with a bigger z..    

        The pic's bellow just show the mock up scene in two states (near  and far), the scene Z is being controlled internally for the time being.  Will just have to wrap up all the necessary setting functions to make it user controllable.    


 EDIT #1 Added a 3rd picture as it's easier to see the scene is sorted and perspective projected.  

 EDIT #2 Added a 4th picture, in this one we see the camera can rotate it's view down the Z axis.    So the sprite aren't rotating, the viewer is.


kevin

    G2D - Alpha Addition Sprite Draw Modes with Perspective Ordered Sprites Scene Test

       It's hot unseasonable warm here the past few days so I've been out on the bike trying to catch up some last minute training for next weekend Around the bay event.    It's only a fun ride, but the preparation can really eat into my free time.   Will be glad when it's over that's for sure.

        Anyway,  during the last session on the library i was toying with dropping in some support for Pb sprite drawmodes / camera rotations.  Unfortunately the GL 1.0x spec is pretty limited when it comes to blend modes,  we can do the most common stuff from PB, such as Alpha blending / Tinting / Additive modes, but some of other would require multiple passes & or special textures..   For the time being it's no big deal..  


       I think what i'll do today is hack together some camera controls and throw up a version of library again...



kevin

  G2D - Zooming Bubble Field

    Those full members of the forums (others won't even be aware it exists) with long memories might remember this demo from the previous GL library for PBFX runtimes.   Basically it's just manually drawing a bunch of zooming bubbles (2500 rects) all alpha bended over each other with shaded backdrop.     It's a bit slower than the optimized PBFX version, as this version is test isn't compiled to DLL (it's just running in normal PB code).  The FX engine is much more optimized than this at this point, but they should run about the same in the end.
   
    The routine bellow draws the scene is bellow..  

PlayBASIC Code: [Select]
      optExpressions  1+2

Type tSprite
X#,Y#,Z#
SpeedX#,SpeedY#
TintColour
endtype

Dim Sprites(2500) as tSprite



Function Render_Sprites(ThisIMage)

local ProjectX#=400
local ProjectY#=400

local Width =getImageWidth(ThisIMage)
local Height=getImageHeight(ThisIMage)
local Width2=Width/2
local Height2=Height/2

local ScreenWidth=GetScreenWidth()
local ScreenHeight=GetScreenHeight()

local scx=ScreenWidth/2
local scy=ScreenHeight/2

local Pad=50

local lp, MaxZ=3000

Local Speed=8
Local Sx#,Sy#
For lp =0 to GetArrayElements(Sprites())

if Sprites(lp)=0
Sprites(lp)= New tSprite

Sprites(lp).x = rndrange(Pad,screenWidth-Pad)-scx
Sprites(lp).y = rndrange(Pad,screenHeight-Pad)-scy
Sprites(lp).z = rnd(MaxZ)

Sprites(lp).TintColour =rnd($ffffff)|(rnd(128)<<24)
repeat
sx# = rndrange(-Speed,speed)
sy# = rndrange(-Speed,speed)
until sx#<>0 and sy#<>0
Sprites(lp).SpeedX=sx#
Sprites(lp).SpeedY=sy#

endif

local z#=Sprites(lp).z-5

if z#<pad
z#=MaxZ
Sprites(lp).x = rndrange(Pad,screenWidth-Pad)-scx
Sprites(lp).y = rndrange(Pad,screenHeight-Pad)-scy
Sprites(lp).z = z#
endif
Sprites(lp).z=Z#

local x#=Sprites(lp).x
local y#=Sprites(lp).y

local Scaler#=ProjectX#/z#

local x1#=(((x#-Width2))*Scaler#)
local x2#=(((x#+Width2))*Scaler#)
local y1#=(((y#-Height2))*Scaler#)
local y2#=(((y#+Height2))*Scaler#)

g2dDrawScaledImage( ThisImage,scx+x1#,scy+y1#,scx+x2#,scy+y2#, Sprites(lp).TintColour,1+8)
next

EndFunction




      Obviously there's a lot of work for the runtime to do driving all the objects from the debug runtimes,  so converting it to a perspective sprite scene should get rid of a lot of that, in particular when this build G2D is compiled to DLL.  


   Edit #1

       Ok, it's mid afternoon now and i've just built the DLL version of the library and have discovered something I'd hoped would happen, but didn't want to preempt it..   Which is that today's build of the G2D DLL through PB2DLL is faster, than PBFX GL DLL built from VisualStudio  (pro edition) - This is surprising as I was expect them to be about the same, but this comes as a very pleasant surprise !

       The second picture is show "test #13" from the basic 2d demo that comes with the G2d proto's.   Obviously the  machine code dll version is quicker than running the test code through the PB runtimes..  The previous picture was drawing something like 2000 sprite rects at 30fps.. (on 9 year old computer :) ) .  The machine code version lets us run 5000 sprites in the perspective scene (Z sorted) at 42/43 fps on the same system.   Which is about 8% quicker than what the same demo runs in PBFX and original GL library..  



    Edit #2 - Released

          Uploaded the 6th generation of the library..    Have fun..

   G2d Download (login required)