Author Topic: [Bmax] Software render framework  (Read 21631 times)

0 Members and 1 Guest are viewing this topic.

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #20 on: July 18, 2009 »
Thanks guys. I just added a function that will copy an image and rotate it to the angle provided.

Code: [Select]
Function rotatecopy:zImageBuffer(from:zImageBuffer,angle:Int)
Local tmp:zImagebuffer = zImageBuffer.copy(from)
tmp.clear()
Local r:Byte,g:Byte,b:Byte,a:Byte
Local wh:Int = (tmp.width/2)-1
Local hh:Int = (tmp.height/2)-1
For Local y:Int = 0 Until tmp.height
For Local x:Int = 0 Until tmp.width
Local tx:Int = (x-wh) * Cos(angle) - (y-hh) * Sin(angle) + wh
Local ty:Int = (y-hh) * Cos(angle) + (x-wh) * Sin(angle) + hh
If tx > -1 And tx < tmp.width And ty > -1 And ty < tmp.height Then
from.getpixel(tx,ty,r,g,b,a)
tmp.setpixel(x,y,r,g,b,a)
End If
Next
Next
Return tmp
End Function

I am a little stuck on ideas to expand on it, so I will take suggestions should there be any :)

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: [Bmax] Software render framework
« Reply #21 on: July 18, 2009 »
Would there be any worth in adding polygons to it? :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #22 on: July 18, 2009 »
Quote
Would there be any worth in adding polygons to it?

Yes that could be an option. I will most likely clean up the code a little bit, optimise the pixel manipulations where possible, complete the bitmap font stuff and then I can add a polygon fill method. I would come in handy should someone want to make some vector effects :) I have all the code for it, it just takes time finding it in my archieves and converting to bmax.

At some point I might decide it to be finished, and perhaps take another look at my opengl stuff, but for now this is keeping me busy and its quite fun actually, so I will stick with it for a while yet. It might serve me well for possible entries to challenges, although the current one with the magnification have not sparked any ideas for me yet.

Which reminds me, that I should do a method that draws an image zoomed :)

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #23 on: July 19, 2009 »
I have just added four methods to the framework. Until now I have only had the copyrect methods, but when you want to draw the entire image buffer into another buffer, then the framework should already know the starting point and width/height of the image. So I added two regular drawing methods, one that draws the image without masking and one that does. And I complemented these with two methods that draws images scaled.

Code: [Select]
Method drawBlock(toImg:zImagebuffer,x:Int,y:Int)
Local pixSourcePtr:Byte Ptr = PixmapPixelPtr(Self.buffer)
Local pixDestPtr:Byte Ptr = PixmapPixelPtr(toImg.buffer)
For Local ty:Int = 0 Until Self.height
For Local tx:Int = 0 Until Self.width
If tx+x > -1 And tx+x < toImg.width And ty+y > -1 And ty+y < toImg.height Then
Local offsetS:Int = ty*Self.pitch+tx*Self.bcount
Local offsetD:Int = (ty+y)*toImg.pitch+(tx+x)*toImg.bcount
pixDestPtr[offsetD] = pixSourcePtr[offsetS]
pixDestPtr[offsetD+1] = pixSourcePtr[offsetS+1]
pixDestPtr[offsetD+2] = pixSourcePtr[offsetS+2]
If Self.bcount = 4 And toImg.bcount = 4 Then pixDestPtr[offsetD+3] = pixSourcePtr[offsetS+3]
End If
Next
Next
End Method

Method drawMasked(toImg:zImageBuffer,x:Int,y:Int)
Local pixSourcePtr:Byte Ptr = PixmapPixelPtr(Self.buffer)
Local pixDestPtr:Byte Ptr = PixmapPixelPtr(toImg.buffer)
For Local ty:Int = 0 Until Self.height
For Local tx:Int = 0 Until Self.width
If tx+x > -1 And tx+x < toImg.width And ty+y > -1 And ty+y < toImg.height Then
If pixSourcePtr[ty*Self.pitch+tx*Self.bcount] <> Self.mask[0] Or pixSourcePtr[ty*Self.pitch+tx*Self.bcount+1] <> Self.mask[1] Or pixSourcePtr[ty*Self.pitch+tx*Self.bcount+2] <> Self.mask[2] Then
Local offsetS:Int = ty*Self.pitch+tx*Self.bcount
Local offsetD:Int = (ty+y)*toImg.pitch+(tx+x)*toImg.bcount
pixDestPtr[offsetD] = pixSourcePtr[offsetS]
pixDestPtr[offsetD+1] = pixSourcePtr[offsetS+1]
pixDestPtr[offsetD+2] = pixSourcePtr[offsetS+2]
If Self.bcount = 4 And toImg.bcount = 4 Then pixDestPtr[offsetD+3] = pixSourcePtr[offsetS+3]
End If
End If
Next
Next
End Method

Method drawScaledBlock(toImg:zImageBuffer,x:Int,y:Int,scaleX:Float,scaleY:Float)
Local pixSourcePtr:Byte Ptr = PixmapPixelPtr(Self.buffer)
Local pixDestPtr:Byte Ptr = PixmapPixelPtr(toImg.buffer)
Local sw:Int = Self.width * scaleX
Local sh:Int = Self.height * scaleY
Local deltaX:Float = Self.width / Float(sw)
Local deltaY:Float = Self.height / Float(sh)
Local cx:Float=0.0,cy:Float=0.0
For Local ty:Int = 0 Until sh
cx = 0.0
For Local tx:Int = 0 Until sw
If tx+x > -1 And tx+x < toImg.width And ty+y > -1 And ty+y < toImg.height Then
Local offsetS:Int = Int(cy)*Self.pitch+Int(cx)*Self.bcount
Local offsetD:Int = (ty+y)*toImg.pitch+(tx+x)*toImg.bcount
pixDestPtr[offsetD] = pixSourcePtr[offsetS]
pixDestPtr[offsetD+1] = pixSourcePtr[offsetS+1]
pixDestPtr[offsetD+2] = pixSourcePtr[offsetS+2]
If Self.bcount = 4 And toImg.bcount = 4 Then pixDestPtr[offsetD+3] = pixSourcePtr[offsetS+3]
End If
cx :+ deltaX
Next
cy :+ deltaY
Next
End Method

Method drawScaledMasked(toImg:zImageBuffer,x:Int,y:Int,scaleX:Float,scaleY:Float)
Local pixSourcePtr:Byte Ptr = PixmapPixelPtr(Self.buffer)
Local pixDestPtr:Byte Ptr = PixmapPixelPtr(toImg.buffer)
Local sw:Int = Self.width * scaleX
Local sh:Int = Self.height * scaleY
Local deltaX:Float = Self.width / Float(sw)
Local deltaY:Float = Self.height / Float(sh)
Local cx:Float=0.0,cy:Float=0.0
For Local ty:Int = 0 Until sh
cx = 0.0
For Local tx:Int = 0 Until sw
If tx+x > -1 And tx+x < toImg.width And ty+y > -1 And ty+y < toImg.height Then
If pixSourcePtr[Int(cy)*Self.pitch+Int(cx)*Self.bcount] <> Self.mask[0] Or pixSourcePtr[Int(cy)*Self.pitch+Int(cx)*Self.bcount+1] <> Self.mask[1] Or pixSourcePtr[Int(cy)*Self.pitch+Int(cx)*Self.bcount+2] <> Self.mask[2] Then
Local offsetS:Int = Int(cy)*Self.pitch+Int(cx)*Self.bcount
Local offsetD:Int = (ty+y)*toImg.pitch+(tx+x)*toImg.bcount
pixDestPtr[offsetD] = pixSourcePtr[offsetS]
pixDestPtr[offsetD+1] = pixSourcePtr[offsetS+1]
pixDestPtr[offsetD+2] = pixSourcePtr[offsetS+2]
If Self.bcount = 4 And toImg.bcount = 4 Then pixDestPtr[offsetD+3] = pixSourcePtr[offsetS+3]
End If
End If
cx :+ deltaX
Next
cy :+ deltaY
Next
End Method

I have updated the first post with the current framework file.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: [Bmax] Software render framework
« Reply #24 on: July 19, 2009 »
So as it does the scaled images now does that mean that you'll be able to enter the Magnification challenge? :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #25 on: July 19, 2009 »
Quote
does that mean that you'll be able to enter the Magnification challenge?

Perhaps, I am not quite sure what I would make though. But I will take another look at the rules and try and think of something.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: [Bmax] Software render framework
« Reply #26 on: July 19, 2009 »
Well there aren't many entries at the moment so there's plenty of ideas left I guess!
Shockwave ^ Codigos
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #27 on: July 19, 2009 »
Well I just did a quick one, I hope people like it. Its not much, but it has something to do with magnification at least :)

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [Bmax] Software render framework
« Reply #28 on: August 07, 2009 »


I finally got some time away from work to tinker with this a bit. This really simplifies coding pixmaps and manipulating them! I'm looking forward to doing some low res work.
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #29 on: August 07, 2009 »
I have been having a bit of fun with it myself the last couple of days, and I am about halfway done with making an intro. I am looking forward to see, what kind of trickery you can come up with.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [Bmax] Software render framework
« Reply #30 on: August 08, 2009 »
I finally managed to run a quick test of my own. I must say that it is VERY good for that low res feeling.

I do have two concerns however.

1 The line function sometimes has breaks in the results.

2 Do you think you could impliment a faster DrawScaledBlock function with powers of 2? Ex drawing a 320x240 chunk to a 640x480 buffer. This is useful for making pixel perfect low res work. Testing with FRAPS the big hit seems to be here, not in the drawing functions, which are really quite good.

Here is my small little test...

Code: [Select]


' test for Zawran's screen buffer library

SuperStrict

Include "Framework.bmx"


'' first draw everything to a small block, then draw the small block to a larger screen block

Global base_buffer:zImageBuffer = zImageBuffer.make(160, 120)
Global scaled_buffer:zImageBuffer = zImageBuffer.make(640, 480)

Graphics(640, 480, 32)
' base rotation angle please
Global rotz:Float = 0
'radius for the star please
Global radius:Float = 64

While Not KeyDown(KEY_ESCAPE)
base_buffer.clear()
scaled_buffer.clear()
If rotz < 360
rotz:+1
Else
rotz:-360
End If

'draw some fun horizontal lines please
For Local y:Float = 0 To 239
'blend 255,0,255 to 255,127,0
Local p:Float = Cos((y * 4) + (rotz * 4))
Local r:Float = 255
Local g:Float = interpolate(0, 127, p)
Local b:Float = interpolate(255, 0, p)
base_buffer.line(0, y, 160, y, r, g, b)
Next

' draw a rotating star please
Local scale:Float = Sin(rotz)
For Local I:Int = 0 To 4
Local r:Byte = Rand(0, 255)
' draw arm one
Local max_radius:Float = radius * scale + 5
Local x1:Float = 80 + Cos(i * 144 + rotz) * max_radius
Local x2:Float = 80 + Cos((i + 1) * 144 + rotz) * max_radius
Local y1:Float = 60 + Sin(i * 144 + rotz) * max_radius * scale
Local y2:Float = 60 + Sin((i + 1) * 144 + rotz) * max_radius * scale
base_buffer.line(x1, y1, x2, y2, 0, 0, 255)
Next

'flip and resize please
base_buffer.drawScaledBlock(scaled_buffer, 0, 0, 4.0, 4.0)
scaled_buffer.blitToScreen()
Flip
Wend

' yes please
Function interpolate:Float(num_1:Float, num_2:Float, p:Float)
Local dif:Float = num_2 - num_1
Return num_2 - (dif * p)
End Function




« Last Edit: August 08, 2009 by Pixel_Outlaw »
Challenge Trophies Won:

Offline TinDragon

  • Pentium
  • *****
  • Posts: 644
  • Karma: 24
    • View Profile
    • J2K's blog
Re: [Bmax] Software render framework
« Reply #31 on: August 08, 2009 »
I dont understan d how the line function is doing that, unless when zawran converted it into the framework something got changed slightly, I cant say its ever done that in all the stuff I used it in.

Due to the way pixmaps are stored in ram all the drawing to them is done via cpu into system ram but the final drawing of the pixmap to the screen is done by bmax, now zawran has set the pixmaps it creates to RGBA format so if you dont set bmax to use opengl for drawing it will use directx7 and that means that the pixmap has to be converted to BGRA before it gets draw, which is bloody slow for some reason. I think you will find a speed improvement by doing that as long as you dont get a bottleneck from gldrawpixels which is how bmax handles drawing the pixmaps then.

I will have a look see if I can spot any error in the line draw.

Cheers
Jon

Offline TinDragon

  • Pentium
  • *****
  • Posts: 644
  • Karma: 24
    • View Profile
    • J2K's blog
Re: [Bmax] Software render framework
« Reply #32 on: August 08, 2009 »
I am not sure why but zawran changed a couple things I did in the line code but even if I swap in my original code it misses pixels in the lib but doesnt seem to in my basic lib, which has me confused  ???

And WoW that code is very slow to draw. I have seen it throw some pretty complex stuff around the screen but you managed to kill it somehow, is that code overwriting alot of areas for the background multiple times or something, I am sure it could do a plasma faster than that. [EDIT] NOTE TO SELF TURN OF DEBUG  :-[





« Last Edit: August 08, 2009 by TinDragon »

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #33 on: August 08, 2009 »
Yes it sure does look like there is a problem with the line method. I will try and figure out whats up. The scaling will always be somewhat slow compaired to other pixel manipulations, expecially when doing large scales. But for power 2 scaling I might be able to speed it up somewhat by only doing the pixel scaling horizontally, and then using memcopy to scale it vertically. But if what you want as an end result is a pixmap scaled to the size of the screen, then you are better of letting the hardware do the scaling:

Code: [Select]
Local tmpImg:TImage = LoadImage(base_buffer.buffer,0) ' load the pixmap into an image and tell it not to smooth when scaling
SetScale(4.0,4.0) ' set the general scaling
DrawImage(tmpImg,0,0) ' draw the scaled image to the screen

the code above would replace the following lines from your code:

Code: [Select]
base_buffer.drawScaledBlock(scaled_buffer, 0, 0, 4.0, 4.0)
scaled_buffer.blitToScreen()

I will see if I cannot make the scaling methods faster though, but I cannot say when it will be done.

[edit] With the help of Jon, we figured out what might be wrong with the line method. Please replace it with the following and see if that doesn't work better:

Code: [Select]
Method line(x1:Float,y1:Float,x2:Float,y2:Float,r:Byte,g:Byte,b:Byte)
Local pixPtr:Byte Ptr = PixmapPixelPtr(Self.buffer)
Local steps:Float,xI:Float,i:Int

x2 :- x1
y2 :- y1

If Abs(x2) > Abs(y2) Then
steps = Abs(x2)
Else
steps = Abs(y2)
End If

xI = Float(x2 / steps)
y2 = Float(y2 / steps)

For x2 = 0 To steps
If Int(y1) > -1 And Int(y1) < Self.height Then
If Int(x1) > -1 And Int(x1) < Self.width Then
Local offset:Int = Int(y1)*Self.pitch+Int(x1)*Self.bcount
pixPtr[offset] = r
pixPtr[offset+1] = g
pixPtr[offset+2] = b
If Self.bcount = 4 Then pixPtr[offset+3] = 255
End If
End If
x1 :+ xI
y1 :+ y2
Next
End Method
« Last Edit: August 08, 2009 by zawran »

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [Bmax] Software render framework
« Reply #34 on: August 08, 2009 »
The lines are looking good now. :)

MUCH faster method of drawing/scaling too. I think I can get a good game out of this with the current speed.
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #35 on: August 08, 2009 »
Quote
I think I can get a good game out of this with the current speed

Glad to hear it, and looking forward to trying the game when done :)

Offline JumpMan

  • C= 64
  • **
  • Posts: 45
  • Karma: 11
    • View Profile
Re: [Bmax] Software render framework
« Reply #36 on: August 10, 2009 »
I decided to check this forum out and saw this. Great work Zawran :clap:. I took the liberty of adding a couple of functions to your library: circle and elipse(not really an elipse its really an oval). I hope you don't mind. It draws them filled and hollow. Also, I added alpha to the line function to keep consistency with the pixel and my functions. I hope this is usefull if not just ignore it.  
« Last Edit: August 10, 2009 by JumpMan »

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [Bmax] Software render framework
« Reply #37 on: August 10, 2009 »
The following functions might be useful...


-Optimized line drawing (Might be useful for gradient filling)
line_horizontal ( optimized horizontal line)
line_verticle (optimized verticle line)

-Pattern filiing/tiling (This would be cool for drawing interesting filled shapes also pseudo screen door transparency)
pattern_draw_rectangle(x,y,width,height, pattern:zImageBuffer) ...ect


I've been playing with this and it can easly render 100 of my little 16x16 sprites in my classic resolution of 360x240! I'm working on a dynamic flower/growth shooting arcade style game now. Basically flowers grow and tangle at the top of the screen and you must destroy the ever budding heads from their stems. Using the 16 color palette from windows.

Works wonders and forces that classic resolution. This is starting to look very retro, in a completely valid sense.
« Last Edit: August 10, 2009 by Pixel_Outlaw »
Challenge Trophies Won:

Offline zawran

  • Sponsor
  • Pentium
  • *******
  • Posts: 909
  • Karma: 67
    • View Profile
Re: [Bmax] Software render framework
« Reply #38 on: August 10, 2009 »
@JumpMan, This is just the reason I keep this framework open, so that everyone can add to it, thanks for taking the time to work on this.

@Pixel_Outlaw, Its a good idea about the pattern filling, and I think I have piece of code I can work into the framework that will do just that. I also thought that a gradient line would be useful, so I will look at adding that as well. The optional lines, horizontal/vertical I think can be done fairly easily, so I will try and get those done as well.

Offline Pixel_Outlaw

  • Pentium
  • *****
  • Posts: 1382
  • Karma: 83
    • View Profile
Re: [Bmax] Software render framework
« Reply #39 on: August 10, 2009 »

I'll mention the framework and you for sure when I finish.  :goodpost:
Challenge Trophies Won: