Author Topic: Scaling down graphics to a UDG level (or something)  (Read 9625 times)

0 Members and 1 Guest are viewing this topic.

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
As you can tell by the title, I'm not sure what I am on about.

Well I saw the UDG demos posted for the UDG compo and really enjoyed the creativeness that was employed by some of you very clever people. I've also been playing with tinyptc for Purebasic and have come to the realisation that to do funky stuff you need to ditch those inbuilt easy command and start poking with your frame buffer. The more complex source codes I check out, the more the frame buffer is being abused and manipulated to gain great effects with speed.

So, I would like to create something UDG-y. using 8x8 pixel blocks. I thought about drawing my routines to a backbuffer then peeking the results and then using a workaround of x*8,y*8 then drawing blocks 8x8 to achieve the results. However, this is where I get back to the framebuffer - my testing seems very slow and I can only imagine once I start getting more funky stuff flopping around the screen, my way of doing things is gonna slow down way too much. And i don't want that.

Here is the code I have put together (purebasic) :

Code: [Select]
InitMouse():InitKeyboard() : InitSprite()
OpenWindow(0,0,0,800,600,"")
OpenWindowedScreen(WindowID(0),0,0,800,600)
; 800 = 100
; 640 = 80
Global spx=CreateSprite(#PB_Any,100,80)
StartDrawing(SpriteOutput((spx)))
For Radius = 25 To 0 Step -1
  Circle(25, 25, Radius, RGB(Random(255), Random(255), Random(255)))
Next

StopDrawing()

Global Dim pos(100,80)

ExamineMouse()

Procedure MakeScreen()
  Static.f angle,sS,Cs,zoom=5
  sS=Sin(angle.f*0.5)*10
  cS=(Cos(angle.f*0.5))
  angle.f+0.51
  ClearScreen(0)
  StartDrawing(SpriteOutput(spx))
  Box(0,0,100,80,#Black)
  For Radius = 25 To 0 Step -1
    Circle(25, 25, Radius-zoom, RGB(Random(255), Random(255), Random(255)))
  Next
  zoom-1
  If zoom<0
    zoom=25
   
    EndIf
  StopDrawing()
 
  DisplayTransparentSprite(spx,50+ss,cS,255)
  StartDrawing(ScreenOutput())
  zoom+1
  For x=1 To 100
    For y=1 To 80
      col=Point(x,y)
      If col>0
        pos(x,y)=(col)
      Else
        pos(x,y)=0
      EndIf
    Next
  Next
  StopDrawing()
  ClearScreen(0)
EndProcedure

Procedure ToUDG()
 
  StartDrawing(ScreenOutput())
 
  For x=1 To 100
    For y=1 To 80
      ;StartDrawing(SpriteOutput(0))
      col=pos(x,y)
      ;StopDrawing()
      If col>0
        ;  FlipBuffers()
        Box(x*8,y*8,8,8,col)
        ;  FlipBuffers()
      EndIf
    Next
  Next
  StopDrawing()
 
EndProcedure
Repeat
  ClearScreen(0)
  MakeScreen()
  ToUDG()
  FlipBuffers()
  ExamineKeyboard()
  WindowEvent()
Until KeyboardPushed(#PB_Key_Escape)

Now as you can see, I am trying to carry out brain surgery using a plunger and a hacksaw - I need to be guided how I can do this sort of stuff with the framebuffer, possibly tinyptc because it seems so quick!

I've attached an exe for you to see if your not a Pb-er..

Thanks in advance!

:)
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #1 on: January 10, 2014 »
hi mate i can see what you are doing here but using pb like that will always be really slow.. there is a ton of extra steps too be done that don't have too if you just grab an area of ram and flush it too the gpu each frame.

ive coded a little freebasic app too show you how with low level pure pixel pushing you can get this done.

its now just a two step process

step 1:
i render the animated udg into its own array.

step 2:
blit the udg too the framebuffer much the same way as a bmp.

doing it this way is pretty much as fast as you can get. and indeed much much faster. now i don't know if pb has a means of working on raw buffers the same way as freebasic but if it does this freebasic example should run roughly the same in pb.

ive added a few little comment's too the source too hopefully help you out but if there is any technical bits you don't understand just fire some questions my way.
« Last Edit: January 10, 2014 by ninogenio »
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #2 on: January 10, 2014 »
i forgot too add the little 8x8 resize in my example but even with this coded in it would still be really really fast.

-edit i have put the re-size in this version it now is the same size as your ver.. i also added a fps counter in the console window when run in windowed mode. with vertical sync on it runs 100% 60fps with vsync off its too fast too see runs at about 200 fps here.
« Last Edit: January 10, 2014 by ninogenio »
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #3 on: January 10, 2014 »
Wow, thanks man!

This'll be really helpful, so it looks like I am correct that if I want to make more impressive quick effects, I need to learn how to blit to the frame buffer. I've never done stuff like that before - but I am doing a lot of things recently that I have never achieved before so this is good!

The example is really healpful, very grateful for that. I have been converting some tintptc FB sources to tinyptc PB, so I should be able to convert this and hopefully I will feel that *plonk* click in my head when you suddenly grasp a concept.

Gonna have a play and see what I do.

Again, tip top! thanks!

 ;D
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #4 on: January 10, 2014 »
yeah framebuffer's are like that they look cryptic at first but all of a sudden things click and you just start thrashing stuff around (anything is possible when pushing individual pixels.. the mind is the limit)

i will try too explain how a 1d array works because that's probably the toughest part too grasp.

basically with framebuffers you will work with arrays like this.

Dim Shared As Integer BackBuffer(Width*height)

rather than

Dim Shared As Integer BackBuffer(Width,Height)

now when i comes time too put an rgb point at say... 100x by 200y how would we do that with a 1d array. thats where this little formula comes in.

xpos+ypos*ScreenWidth

that formula will always point too the correct element in the array so

BackBuffer(100+200*screenWidth) = rgb(255,0,0)

would store a red dot in the back buffer array at 100,200.  :)

then with ptc its just
Ptc_Update( BackBuffer )

what that does is map each element of the backbuffer directly too screen pixels so it would light a red dot up at 100,200

now im sorry if you already knew this. its just that for some folks this is the part that when they get over it things just click!

while your having a mess around if there is anything your not sure of just ask away mate.
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #5 on: January 11, 2014 »
That's really helpful, no I didn't know this, thanks!

Really going to hammer this out this weekend :)

 :updance:
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #6 on: January 13, 2014 »
how is your framebuffer adventures coming along emook?
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #7 on: January 13, 2014 »
Unfortunately due to certain things, likes kids and missus!, I did not get the chance I wanted. Going to see if I can give it a whirl today :)
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #8 on: January 13, 2014 »
excellent! well i still have pb installed here so if there is anything i can help with just give me a shout  :cheers:
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #9 on: January 19, 2014 »
Hello again!

Ok, I didnt have a lot of time last weekend and have come back to this. (spent a while playing with the old basic routine to try and come up with some ideas!)

So last night I began converting, I managed to get the circle to display but it looks like I am only reading 1bitplane, or 2bytes from memory rather than the expected 4 giving strange results.

I had to stop after many hours of tweaking, could you have a look for me?

 :carrot:

In the archive is your example, my PB version & compiled exe (I am not bothered about movement at the moment) with the tinyptc library this needs to go into your PB folder PureLibraries\UserLibraries.

Once I figure this out I want to be able to load an image into memory and do the same thing.... 

Thanks in advance!

https://dl.dropboxusercontent.com/u/2940985/framebuffer_ptc.rar
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #10 on: January 19, 2014 »
hi mate yes i will have a proper look a little later for you. just had a quick skim over and one thing jumps out...

Global *udgptr=AllocateMemory(WidthX*HeightY)
Global *Buffer=AllocateMemory(WidthX*HeightY)

now i am not sure how pb works but with ever other language i have worked in, when allocating memory you have too multiply the number of elements by the number of bytes required for each element.

so those two would be.

Global *udgptr=AllocateMemory((WidthX*HeightY)*4)
Global *Buffer=AllocateMemory((WidthX*HeightY)*4)

as its 32 bits(r/g/b/a) or 4 bytes per pixel.

thats just a stab atm though ill have a proper look in a bit
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #11 on: January 19, 2014 »
Ahh yes! I should have remembered the *4 - I've added that in but still having the same issue - i think its someting to do with converting the colour into the correct rgba component.

Look forward to your reply! :)
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #12 on: January 19, 2014 »
i am on the trial version of pb emook so it wont let me use the tiny ptc lib :(

however i think i have found your error have a look in here..

Code: [Select]
Procedure RenderCircle(*Buffer,Xpos,Ypos,Radi.f,WdthX,HghtY,Colour)
   
     Radi2.f
    ; Z
;     Dim W As Double
;     Dim X As Integer
   
    If Radi>0
        Radi2 = ( Radi * Radi )
        For Z=-Radi To Radi
            W = Sqr( Radi2 - Z * Z )
            If ( Z + Ypos )  < HghtY - 1 And ( Z + Ypos ) > 1
                For X = Xpos - W To Xpos + W
                    If X < WdthX - 1 And X > 1
                       ; Buffer[ ( Z + Ypos ) * WdthX + X ] = Colour
                       pos=(Z+Ypos)*WdthX+X
                       PokeB(*Buffer+pos,Colour)
                    ;   Debug Colour
                    EndIf
                Next
            EndIf
        Next
    EndIf
   
EndProcedure

Procedure RenderIntoUdgBuffer()
   
    Protected.I sS,Cs
    Protected.I x,Y,Radius
   
    sS=(Sin(Angle*0.5)*10.0)
    cS=(Cos(Angle*0.5))
   
    Angle+0.51
   
    For Radius = 25 To 0 Step -1
      ;  RenderCircle(@UdgBuffer(0), 35, 35, Radius-zoom,UdgWidth,UdgHeight, RGB(Random(255,1), Random(255,1), Random(255,1)))
       RenderCircle(@UdgBuffer(0), 35, 35, Radius-zoom,UdgWidth,UdgHeight, RGB(Random(255,1), Random(255,1), Random(255,1)))
       ; RenderCircle(@UdgBuffer(0), 35, 35, Radius-zoom,UdgWidth,UdgHeight,RGB(255,255,255))
    Next
    zoom-1
    If zoom<0
        zoom=25
    EndIf
EndProcedure

first this.
Code: [Select]
Procedure RenderCircle(*Buffer,Xpos,Ypos,Radi.f,WdthX,HghtY,Colour)

should be
Code: [Select]
Procedure RenderCircle(*Buffer,Xpos,Ypos,Radi.f,WdthX,HghtY,ColourR,ColourG,ColourB)

and then here.
Code: [Select]
PokeB(*Buffer+pos,Colour)

should be.
Code: [Select]
PokeInt(*Buffer+pos,(ColourR shl 16) Or (ColourG shl 8) Or (ColourB) )

now i dont know how pb does arithmatic shift lefts so just change the shl too the proper symbol/word your language expects. and then i am pretty sure it will work!  :cheers:
« Last Edit: January 19, 2014 by ninogenio »
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #13 on: January 19, 2014 »
Oh my god! this is driving me mad! :) Thanks for the help again -

I have made the changes, but get the same results. When I am poking integers the circle ends up torn like so :



When I poke bytes I get :



as you can see there is a shadow of around four pixels underneath.

I also tried to change to this part in the rendercircle proc :
Code: [Select]
IPokeB(*Buffer+pos,RGB(ColourR,Colourg,Colourr))

to this :

Code: [Select]
BackBuffer(pos)=(ColourR << 16) | (Colourg << 8) | (Colourb)
The colour appears correct, for example I have set r to 255 but then I get this :



Colour is correct but the place of the image isn't! My poor brain!

 :crutches: :crutches: :crutches:
« Last Edit: January 19, 2014 by emook »
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #14 on: January 19, 2014 »
i like this line much better.
Code: [Select]
BackBuffer(pos)=(ColourR << 16) | (Colourg << 8) | (Colourb)

and the fact you are getting your specified color means you probably have fixed that part of your code.

i think you are having trouble from here too.
Code: [Select]
BackBuffer( (Xpos+X+Rx)+(Y+Ypos+Ry)*WidthX ) = PeekB(*UdgPtr+X+Y*WdthX)

its most definitely int's you want too write too the back buffer i would just change it too something like..
Code: [Select]
BackBuffer( (Xpos+X+Rx)+(Y+Ypos+Ry)*WidthX ) = UdgPtr[X+Y*WdthX]

have you added the *4 too you allocs as well because now you are writting and reading int's is when that would show up.
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #15 on: January 19, 2014 »
Yes I have added the *4 for the memory allocation. I'm totally stumped with this now.

There must be something quite fundamental regarding Purebasic that I am not doing here.

I don't understand why I use Ints everything seems to go wrong.

What I am planning to do this evening is painstakingly sit and add a load of break points and compare the memory address contents. Maybe that will shed some light on what I am not doing correctly.

I went to sleep at 4 am last night after trying to figure out how to fix this, and then lay in bed coming up with all sorts of potential fixes. Looks like tonight will be the same.

No doubt I will kick myself when someone finally shows me the way! :)

 :inspired:
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #16 on: January 19, 2014 »
after a quick mess around here is it working.

Code: [Select]


; Structure Type
; Type.TimerType
;     
;     Frequency As LARGE_INTEGER
;     LiStart As LARGE_INTEGER
;     LiStop As LARGE_INTEGER
;     LlTimeDiff As LONGLONG
;     MDuration As Double
;
; End Type


Declare RenderLine(StartX,StartY,EndX,EndY,Col)
Declare RenderIntoUdgBuffer()
Declare RenderUdg(Xpos,Ypos,WdthX,HghtY)
Declare OpenPtcWindow()
Declare RenderCircle(Xpos,Ypos,Radi.f,WdthX,HghtY,ColourR,ColourG,ColourB)


Global Dim Buffer.l(800*640)
ptc_setdialog(1,"",1,0)
ptc_allowclose(1)
ptc_open("TinyPTCExt",800,640)

Global WidthX = 800
Global HeightY = 640
Global Dim BackBuffer.l(WidthX*HeightY)
For i=0 To WidthX*HeightY
  BackBuffer(i)=$402020
Next

Global UdgWidth = 100
Global UdgHeight = 80
Global Dim UdgBuffer.l(UdgWidth*UdgHeight)
Global Angle, Zoom = 5
Global Dim udgptr.l(WidthX*HeightY)
Global Dim Buffer.l(WidthX*HeightY)

;OpenPtcWindow()
Xpos=1
XAngle.f = 0.1
; Global StepY
; Global YPos
;While ( GetAsyncKeyState( VK_ESCAPE ) <> -32767 )
Repeat

    ;Dim Y,X
   
    ;this draws into an object udg buffer of size x=100 y=80
    RenderIntoUdgBuffer()
   ; Xpos+(Sin(XAngle*0.8)*13.0)
   ; XAngle + 0.1

    ;this does a blit of our just generated udg into the back buffer at 300,200
    RenderUdg(Xpos, 0, UdgWidth, UdgHeight )
   
    ;this flips the back buffer
  ;  ptc_update( ;@BackBuffer(0) )
    ptc_update( @BackBuffer(0) )
   
    ;this clears the back buffer
    For x = 0 To (WidthX-1)*(HeightY-1)
        BackBuffer(X) = RGB( 60, 0, 0 )
    Next
   

ForEver


Procedure RenderUdg(Xpos,Ypos,WdthX,HghtY)
   
; ;   GetObject_(ImageID(img), SizeOf(BITMAP), @bmp.BITMAP)
; ;   Protected imagesize = bmp\bmWidthBytes * bmp\bmHeight
; ;   Protected *bits = bmp\bmBits
 
    ; blit and upscale udg into back buffer
    StepY=Ypos
    For Y = 0 To HghtY-1
        For Ry = StepY To StepY+4
            For X = 0 To WdthX-1
                For Rx = StepX To StepX+4
                  If UdgPtr(X+Y*WdthX)<>$0
                 ; If PeekI(*bits+X+Y*WdthX)<>$0
                    ;Debug "hit"
                       ;BackBuffer( (Xpos+X+Rx)+(Y+Ypos+Ry)*WidthX ) = PeekB(*bits+X+Y*WdthX)
                        BackBuffer( (Xpos+X+Rx)+(Y+Ypos+Ry)*WidthX ) = UdgPtr(X+Y*WdthX)
                     EndIf
                Next
                StepX+4
             
            Next
            StepX=0
          Next
         
        StepY+4
    Next
   
EndProcedure

Procedure OpenPtcWindow()
    ptc_allowclose(0)
    ptc_setdialog(1,"udg test"+"FullScreen",1,0)
    ptc_setflip(0)
    ptc_open("udg", WidthX, HeightY)
      ;  End - 1
    ;EndIf
EndProcedure



Procedure RenderCircle(Xpos,Ypos,Radi.f,WdthX,HghtY,ColourR,ColourG,ColourB)
   
     Radi2.f
    ; Z
;     Dim W As Double
;     Dim X As Integer
   
    If Radi>0
        Radi2 = ( Radi * Radi )
        For Z=-Radi To Radi
            W = Sqr( Radi2 - Z * Z )
            If ( Z + Ypos )  < HghtY - 1 And ( Z + Ypos ) > 1
                For X = Xpos - W To Xpos + W
                    If X < WdthX - 1 And X > 1
                       ; Buffer[ ( Z + Ypos ) * WdthX + X ] = Colour
                       pos=(Z+Ypos)*WdthX+X
                       Udgptr(pos) = (ColourR << 16) | (ColourG << 8) | (ColourB)
                    ;   Debug Colour
                    EndIf
                Next
            EndIf
        Next
    EndIf
   
EndProcedure

Procedure RenderIntoUdgBuffer()
   
    Protected.I sS,Cs
    Protected.I x,Y,Radius
   
    sS=(Sin(Angle*0.5)*10.0)
    cS=(Cos(Angle*0.5))
   
    Angle+0.51
   
    For Radius = 25 To 0 Step -1
      ;  RenderCircle(@UdgBuffer(0), 35, 35, Radius-zoom,UdgWidth,UdgHeight, RGB(Random(255,1), Random(255,1), Random(255,1)))
       RenderCircle( 35, 35, Radius-zoom,UdgWidth,UdgHeight, Random(255,1), Random(255,1), Random(255,1))
       ; RenderCircle(@UdgBuffer(0), 35, 35, Radius-zoom,UdgWidth,UdgHeight,RGB(255,255,255))
    Next
    zoom-1
    If zoom<0
        zoom=25
    EndIf
EndProcedure

now i have stripped it back too a basic level as you can see so if you very carefully take it from here it will work the way you had it.

one thing too note is that your pointers were getting messed up while being passed through the functions.

if you have an allocated pointer such as udgptr you dont pass this through as @someptr(0) you just pass it through as someptr, in your function decleration you will probably want too let it know that a ptr is going too be coming so something like

Code: [Select]
function thisfunction( someptr as ptr,width,height,x,y)

the too call this you would just do thisfunction( someptr,200,100,0,0);
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #17 on: January 19, 2014 »
Is there an icon the has a bott kicking my own ass?!

Thank you very much, I was going way too complex for what was needed it seems. Hmm!

 :sunny: :sunny: :sunny: :sunny:

I think I may have done something like that early on but abandoned when I had issues with the correct colour (the (ColourR << 16) | (ColourG << 8) | (ColourB) bit). Anyway well done and thanks again.

My next task would be to read an image and then put that into the buffer to be displayed!...

 :)
----

R Tape loading error, 0:1

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #18 on: January 20, 2014 »
 :) i think your doing great stuff emook keep at it!!

i have a basic little bmp ptc image loader in freebasic i can post tomorrow if you like..
Challenge Trophies Won:

Offline emook

  • C= 64
  • **
  • Posts: 94
  • Karma: 12
    • View Profile
Re: Scaling down graphics to a UDG level (or something)
« Reply #19 on: January 20, 2014 »
Thanks!

However I have managed to sort out displaying a image from memory. Turns out it was quite easy :)
----

R Tape loading error, 0:1