Masking - how to get about creating a Worm clone?

BlitzMax Forums/BlitzMax Programming/Masking - how to get about creating a Worm clone?

Casaber(Posted 2015) [#1]
What would be a good way to punch holes in a gameīs playfield using Bmax?

Iīm thinking something like this
Put a copy of the game playfield into a temporary fullscreen buffer (I guess this is a problem if one have a huge world so alternative solutions are very welcome)

The main drawing loop would look like this
1) Paint the background
2) Paint the temp playfield ontop
3) paint sprites

And to get the playfield to explode into holes, you would erase somehow (instead of drawing), how would you do that?
I would like to erase using the shape of an image instead to have the holes to be certain shapes.

At the next level you copy a new fresh playfield into this temp.

How would you erase inside an image? (I have the drawing image in an image going on, using VBO right now)
So drawing are working perfectly, but how do you erase using images?

Also, how would you do it? Iīll bet there are thousand of ways doing this, I just picked this way right now as it
felt the closest to what I already had going on.


dw817(Posted 2015) [#2]
Can you post an image example of this, Casaber ? Maybe two images - BEFORE and AFTER, perhaps with a paint program ? I might be able to help if I could visually see what you are saying.


Casaber(Posted 2015) [#3]
Sure, So I made this mockup which should be the before and after playfields.

I want to use sprites I usuallly draw with to cookiecut the landscape effeciently somehow. Iīm not sure what would be the best strategy (and Iīm not able to do it in practice yet using ANY strategy) Any ideas?




Brucey(Posted 2015) [#4]
Couldn't you have a 1bpp mask that represents the visible/destructed surface, and simply mask out stuff with bit set to 0, and draw stuff with bit set to 1?

You could also use this mask for collision detection.

:-)


therevills(Posted 2015) [#5]
I cooked up a Worms like clone a few years a go:

http://www.blitzmax.com/Community/posts.php?topic=89848

Its not perfect but shows a different way to do it...




dw817(Posted 2015) [#6]
Oh ... Looking at therevill's game demo. Yeah, that's not hard to do at all.

Shoot. Just have a static background, and pop some circles in for good effect. You'll need some masking for that. I did something like this in GFA years ago, called it Cookie Cutter. Lemme see ...

Strict
Graphics 640,480
SetBlend alphablend
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)



Now this works but there is something unusual. It starts to slow down the more circles you cut. Any ideas on why it's doing this, guys ?


Casaber(Posted 2015) [#7]

Couldn't you have a 1bpp mask that represents the visible/destructed surface, and simply mask out stuff with bit set to 0, and draw stuff with bit set to 1?



Sounds like an idea but do you mean keeping bitmask in an array or bank or are there hardwareaccelerated features to do this somehow?

@ therevill's I will have to take some time and look carefully into that code, thanks a alot for that.


Now this works but there is something unusual. It starts to slow down the more circles you cut. Any ideas on why it's doing this, guys ?



Nice. The slowdown with time must be something going on with the GrabImage? Maybe itīs reallocating or something and not reusing things not that I understand exactly how that would be. Weird. That was a short and simpel solution, such a pity that it had that slowdown I shall think about this.


Brucey(Posted 2015) [#8]
Sounds like an idea but do you mean keeping bitmask in an array or bank or are there hardwareaccelerated features to do this somehow?

It's probably doable using shaders with very little overhead.


Casaber(Posted 2015) [#9]
Shaders are great solution for many things but right now I'm trying to avoid that while Iīm learning the first steps of BlitzMax. When I add shader, it will probably bunch together more problems and solutions things into ones single one. Which is nice.
And I'm of looking forward to that. But the reality check tells me I need to try and solve it without those kind of solutions right now.


dw817(Posted 2015) [#10]
Yeah, no kidding, Casaber. Really strange. Minju, if someone else has a source example to do the same with no increased delays per grabimage, would love to see it.

Can always learn something new. :)


Casaber(Posted 2015) [#11]
dw817

Here is a template, which setups up 2 buffers and paints to both and shows how to copy one to another. I need to sleep now, but I think you'll find this very useful maybe it could be used for this problem I'm having, your example makes me think; hell yes ;) (you donīt need to understand or read the actual functions they just switch the actual buffers and you see how to do that in the main loop. I would guess itīs 10-100 times faster than GRABIMAGE.

Look at it as if you suddenly got SETBUFFER from Blitz3D (or heaven) into Blitzmax.


HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit
SetBlend(MASKBLEND) ; Local xd = 2

' init img
Global img = CreateImage(512,512,1)
Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) 

' init img2
Global img2 = CreateImage(512,512,1)
Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 

' -------------------------------
While Not MouseDown(2)

' Draw onto img (note that y coordinate is inverted)
IB.BindBuffer() 
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ' draw something
'DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' this copies img2 to img
IB.UnBindBuffer() 

' Draw onto img2  (note that y coordinate is inverted)
IB2.BindBuffer()
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ' draw something
'DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' this copies img to img2
IB2.UnBindBuffer() 

' Draw onto backbuffer (normal)
SetViewport 0,0,1920,1080 ; Cls
'For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(127)),Int(Rnd(63+16)) ; Next
DrawImage img,xsprite,0 ' draw img
DrawImage img2,512,0 ' draw img2

xsprite=xsprite + xd
If xsprite > ((1920 - (32*16))/4) Then xd = - xd
If xsprite < 0 Then xd=-xd

Delay 1 ; Flip 1
Wend
End

' -------------------------------

Rem
Strict
Graphics 640,480
SetBlend alphablend
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
EndRem

' -------------------------------

Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#12]
dw817

Here is a template, which setups up 2 buffers and paints to both and shows how to copy one to another. I need to sleep now, but I think you'll find this very useful maybe it could be used for this problem I'm having, your example makes me think; hell yes ;) (you donīt need to understand or read the actual functions they just switch the actual buffers and you see how to do that in the main loop. I would guess itīs 10-100 times faster than GRABIMAGE.

Look at it as if you suddenly got SETBUFFER from Blitz3D (or heaven) into Blitzmax.


HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit
SetBlend(MASKBLEND) ; Local xd = 2

' create images
Global img = CreateImage(512,512,1)
Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) 

Global img2 = CreateImage(512,512,1)
Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 

' -------------------------------
While Not MouseDown(2)

' Draw onto img (note that y coordinate is inverted)
IB.BindBuffer() 
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ' draw something
'DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' this copies img2 to img
IB.UnBindBuffer() 

' Draw onto img2  (note that y coordinate is inverted)
IB2.BindBuffer()
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ' draw something
'DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' this copies img to img2
IB2.UnBindBuffer() 

' Draw onto backbuffer (normal)
SetViewport 0,0,1920,1080 ; Cls
'For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(127)),Int(Rnd(63+16)) ; Next
DrawImage img,xsprite,0 ' draw img
DrawImage img2,512,0 ' draw img2

xsprite=xsprite + xd
If xsprite > ((1920 - (32*16))/4) Then xd = - xd
If xsprite < 0 Then xd=-xd

Delay 1 ; Flip 1
Wend
End

' -------------------------------

Rem
Strict
Graphics 640,480
SetBlend alphablend
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
EndRem

' -------------------------------

Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



dw817(Posted 2015) [#13]
Hmm ... That's a lot of code, Casaber. By changing the top line to:
HideMouse ; TImageBuffer.Init(1920,1080)',32,60)


When I run it, I just get a bunch of random pixels appearing at the top and some sliding in from the left to the right and back again, a copy from what is being created static.

Is that what is supposed to happen ?

Let me see if I can write some code to show very close to what I'm seeing:
Strict
Local d=1,x=-512,pic:TPixmap,img:TImage
Graphics 1024,512
SetBlend lightblend
pic=GrabPixmap(0,0,512,64)
Repeat
  Cls
  pic.pixels[Rand(512*64*4)]=Rand(256)
  img=LoadImage(pic)
  DrawImage img,x,0
  DrawImage img,0,0
  Flip
  x:+d
  If x>=0 Or x<=-512
    d=-d
  EndIf
Until KeyDown(32)



Casaber(Posted 2015) [#14]
Yup :) those are two images img and img which are drawn onto, before drawing themselves as normal sprites to the screen. Itīs just a plotting colorful dots demo which shows two of these buffers in action, and yup the demo moves one of those sprites.

Notice how there are NO slowdowns for drawing to them, itīs just if we just drew onto the screen. No substantial time is consumed for switching buffers or drawing them etc. It just flows right on.

No thereīs not much code, I put dashes (-------) around the actual code
what comes next is your code that I meant to re-implement. But never got to that point.
Rest are just helper functions you donīt need to care about for starters.


Casaber(Posted 2015) [#15]
Cleaner version (and look here, also I put everything important in this one from the other thread aswell). So this is the holy grail you should be using.
I has no array errors either. I shall check into your code next, this will be great.

I simplified it, simpler moving sprites in this one for a better reading experience, just splatting two images are just fine I guess. I want the readability.
I would like to make an more interesting demo where you copy from eachothers images, you know, just parts, but Itīs really that straightforward, I just need some time to sit down and come up with ideas.

1) Set the wanted destinationbuffer (see it as your SETBUFFER) e.g. IB2.BindBuffer()
2) Use DrawSubImageRect sourceimage,x,y,w,h,sx,sy,sw,sh
3) Tell that youīre finished with the buffer using e.g. IB2.UnBindBuffer() ' now the normal backbuffer is your canvas again

But I think I would like to solve the inverted y coordinates "problem" before I go further becuase thatīs a pain to invert Y all the time in my head. I really would like that, and also get away with the :TImageBuffer = TImageBuffer.SetBuffer() at initiliasing images, just becuase it would look better.


HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit (or skip 32,60 for windowed version)
SetBlend(MASKBLEND)

' Init images (I shall recode the need for the IB part if possible, but right now just see it as a package deal when you create an image to create a unique IB aswell, just look at the 2 examples and mimic new names)
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 

' ------------------------------- MAIN LOOP -----------------------------------

While Not MouseDown(2)

IB.BindBuffer()	' SETBUFFER img (AKA IB)
' Draw anything as usual here
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255
' DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' example how to copy img2 to img
' DrawSubImageRect img,0,128-0,128,-128, 0,0,128,128  ' example how to copy img to img (doing nothing, just out of curiousity and ideas)
IB.UnBindBuffer() 'END

IB2.BindBuffer() ' SETBUFFER img2 (aka IB2) 
' Draw anything as usual here
For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 
' DrawSubImageRect img,0,128-0,128,-128, 0,0,128,128  ' example how to copy img to img2
' DrawSubImageRect img2,0,128-0,128,-128, 0,0,128,128 ' example how to copy img2 to img2 (doing nothing, just out of curiousity and ideas)
IB2.UnBindBuffer() 'END

' Drawing to normal backbuffer now, nothing special

Cls 
DrawImage img,xsprite,0	' Draw img
DrawImage img2,512,0	' Draw img2
xsprite = xsprite + 1 ; xsprite = xsprite Mod 1000

Delay 1 ; Flip 1
Wend

' ------------------------------- MAIN LOOP -----------------------------------

End
































Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)

Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#16]
This could be used for you know, if you hate to begin a new screen each and every frame (youīre forced to use a CLS to be sure to cover ALL machines you know, and usually you msy never ever rely on that things are stillthere from previous frames, which could be a gamechanger in how you need to code, and a drag sometimes).

This way you could draw to an offline buffer, big as the screen. And just say go to hell with the backgroundbuffer and draw onto a offline buffer instead. Things will stay there.

It's a way to do it. I like it. You donīt have to wait for things to be copied over the bus at all (but you still need to sacrifice fillrate), but that's cheap.


Casaber(Posted 2015) [#17]
Dontīt look at this for reference I just wanted to show an example how to create 8 512x512 sprites (or youcould look at them as atlases or offscreenbuffers aswell) and draw to all of them individually, and to show a buffer to buffer copy in action.
And here DrawSubImageRect really comes into play in when you want to do things with those buffers.

You can draw (aka copy) parts from buffer to buffer, to all of your hearts content at amazing speeds, no cost really. Just draw and forget it happened. Really nice.

HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit (or skip 32,60 for windowed version)
SetBlend(MASKBLEND)

' Init images (I shall recode the need for the IB part if possible, but right now just see it as a package deal when you create an image to create a unique IB aswell, just look at the 2 examples and mimic new names)
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 
Global img3 = CreateImage(512,512,1) ; Local IB3:TImageBuffer = TImageBuffer.SetBuffer(Img3)
Global img4 = CreateImage(512,512,1) ; Local IB4:TImageBuffer = TImageBuffer.SetBuffer(Img4) 
Global img5 = CreateImage(512,512,1) ; Local IB5:TImageBuffer = TImageBuffer.SetBuffer(Img5)
Global img6 = CreateImage(512,512,1) ; Local IB6:TImageBuffer = TImageBuffer.SetBuffer(Img6) 
Global img7 = CreateImage(512,512,1) ; Local IB7:TImageBuffer = TImageBuffer.SetBuffer(Img7)
Global img8 = CreateImage(512,512,1) ; Local IB8:TImageBuffer = TImageBuffer.SetBuffer(Img8) 
' ------------------------------- MAIN LOOP -----------------------------------

While Not MouseDown(2)

' Draw to 8 images (offscreenbuffers if you like)
IB.BindBuffer()  ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(511-50)),50+Int(Rnd(511-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END
IB3.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB3.UnBindBuffer() 'END
IB4.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB4.UnBindBuffer() 'END
IB5.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB5.UnBindBuffer() 'END
IB6.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB6.UnBindBuffer() 'END
IB7.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB7.UnBindBuffer() 'END
IB8.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB8.UnBindBuffer() 'END


' Letīs say I want to copy img (aka IB) to img8 (aka IB8), just to see it working (let's for instance copy the whole buffer to another as it is, as that's a nice thing to be able to do)
IB8.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB8.UnBindBuffer() 

' Something come to my mind ---------------- 
' This demo does not show that well that it is actually an mask/alpha draw thatīs happening, so you may easly layer things, from layer to layer and from itself to another part of itself for instance.
' So it's a bad example showing of the REAL strength that IS happening, as we draw ovals which stay in place from the next frame so when it copies/draws from one to another, you never see that it layers, as its already there.
' So you never notice that it IS masked, it just looks like an opaque copy, but itīs not. Itīs a normal (and wonderfully alphamasked) draw that happens, as you would expect with DrawImage, DrawRect and DrawSubImageRect.
' --------------

' Drawing to normal backbuffer now, nothing special

Cls

DrawImage  img,xsprite*1,0	' Draw img	
DrawImage img2,xsprite*2,0	' Draw img2
DrawImage img3,xsprite*3,0	' Draw img3
DrawImage img4,xsprite*4,0	' Draw img4
DrawImage img5,xsprite*5,0	' Draw img5
DrawImage img6,xsprite*6,0	' Draw img6
DrawImage img7,xsprite*7,0	' Draw img7
DrawImage img8,xsprite*7,0	' Draw img8

xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/8)

Delay 1 ; Flip 1
Wend

' ------------------------------- MAIN LOOP -----------------------------------

End






















Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)

Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#18]
Dontīt look at this for reference I just wanted to show an example how to create 8 512x512 sprites (or youcould look at them as atlases or offscreenbuffers aswell) and draw to all of them individually, and to show a buffer to buffer copy in action.
And here DrawSubImageRect really comes into play in when you want to do things with those buffers.

You can draw (aka copy) parts from buffer to buffer, to all of your hearts content at amazing speeds, no cost really. Just draw and forget it happened. Really nice.

HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit (or skip 32,60 for windowed version)
SetBlend(MASKBLEND)

' Init images (I shall recode the need for the IB part if possible, but right now just see it as a package deal when you create an image to create a unique IB aswell, just look at the 2 examples and mimic new names)
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 
Global img3 = CreateImage(512,512,1) ; Local IB3:TImageBuffer = TImageBuffer.SetBuffer(Img3)
Global img4 = CreateImage(512,512,1) ; Local IB4:TImageBuffer = TImageBuffer.SetBuffer(Img4) 
Global img5 = CreateImage(512,512,1) ; Local IB5:TImageBuffer = TImageBuffer.SetBuffer(Img5)
Global img6 = CreateImage(512,512,1) ; Local IB6:TImageBuffer = TImageBuffer.SetBuffer(Img6) 
Global img7 = CreateImage(512,512,1) ; Local IB7:TImageBuffer = TImageBuffer.SetBuffer(Img7)
Global img8 = CreateImage(512,512,1) ; Local IB8:TImageBuffer = TImageBuffer.SetBuffer(Img8) 
' ------------------------------- MAIN LOOP -----------------------------------

While Not MouseDown(2)

' Draw to 8 images (offscreenbuffers if you like)
IB.BindBuffer()  ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(511-50)),50+Int(Rnd(511-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END
IB3.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB3.UnBindBuffer() 'END
IB4.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB4.UnBindBuffer() 'END
IB5.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB5.UnBindBuffer() 'END
IB6.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB6.UnBindBuffer() 'END
IB7.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB7.UnBindBuffer() 'END
IB8.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB8.UnBindBuffer() 'END


' Letīs say I want to copy img (aka IB) to img8 (aka IB8), just to see it working (let's for instance copy the whole buffer to another as it is, as that's a nice thing to be able to do)
IB8.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB8.UnBindBuffer() 

' Something come to my mind ---------------- 
' This demo does not show that well that it is actually an mask/alpha draw thatīs happening, so you may easly layer things, from itself to another buffer or from itself to another part of itself for instance.
' So it's a bad example showing of the REAL strength that IS happening, as we draw ovals which stay in place from the next frame so when it copies/draws from one to another, you never see that it layers, as its already there.
' So you never notice that it IS masked, it just looks like an opaque copy, but itīs not. Itīs a normal (and wonderfully alphamasked) draw that happens, as you would expect with DrawImage, DrawRect and DrawSubImageRect.
' --------------


' Drawing to normal backbuffer now, nothing special

Cls

DrawImage  img,xsprite*1,0	' Draw img	
DrawImage img2,xsprite*2,0	' Draw img2
DrawImage img3,xsprite*3,0	' Draw img3
DrawImage img4,xsprite*4,0	' Draw img4
DrawImage img5,xsprite*5,0	' Draw img5
DrawImage img6,xsprite*6,0	' Draw img6
DrawImage img7,xsprite*7,0	' Draw img7
DrawImage img8,xsprite*7,0	' Draw img8

xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/8)

Delay 1 ; Flip 1
Wend

' ------------------------------- MAIN LOOP -----------------------------------

End






















Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)

Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#19]
Want to try the speed on your machine?

I will try this on my pc shortly but on imac I get 60fps no problem. Itīs fluid all the way.

It's just a simple test (it's a nice scenario I think.)
1) It draws to 32 512x512 images
2) it copies 8 of those 512x512 To eachother, just to test the speed
3) it draws 32 512x512 of them onto the screen, you cannot see all as they are overlapping half of them at least.

As 8 512x512 has about the same coverage as one 1920 x 1080 fullscreen, this means 32 of the means little more than 4 layers of full-HD.

This is by no menas the limit but I think itīs good enough I donīt want too much Right now.
I think itīs very usable in practice for making fluid games. PIXMAP no more. Good riddance.


' Later:
' fix why does graphics gets transparent if eg you draw ovals etc in backbuffer?
' fix simple init
' fix not end
' fix inv y
' bug in demo or why do they change appearence with time in that weak layering effect?
' need to check the edges, bc wach that middle line how affected it is, it should be a tight fit sprite agiast sprite. There's a line artifact. I should check that carefully.

HideMouse ; TImageBuffer.Init(1920,1080,32,60) 'Same as Graphics but set to GLDriver + glewinit (or skip 32,60 for windowed version)
SetBlend(MASKBLEND)

' Init images
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 
Global img3 = CreateImage(512,512,1) ; Local IB3:TImageBuffer = TImageBuffer.SetBuffer(Img3)
Global img4 = CreateImage(512,512,1) ; Local IB4:TImageBuffer = TImageBuffer.SetBuffer(Img4) 
Global img5 = CreateImage(512,512,1) ; Local IB5:TImageBuffer = TImageBuffer.SetBuffer(Img5)
Global img6 = CreateImage(512,512,1) ; Local IB6:TImageBuffer = TImageBuffer.SetBuffer(Img6) 
Global img7 = CreateImage(512,512,1) ; Local IB7:TImageBuffer = TImageBuffer.SetBuffer(Img7)
Global img8 = CreateImage(512,512,1) ; Local IB8:TImageBuffer = TImageBuffer.SetBuffer(Img8)
Global img9  = CreateImage(512,512,1) ; Local IB9:TImageBuffer = TImageBuffer.SetBuffer(Img9)
Global img10 = CreateImage(512,512,1) ; Local IB10:TImageBuffer = TImageBuffer.SetBuffer(Img10) 
Global img11 = CreateImage(512,512,1) ; Local IB11:TImageBuffer = TImageBuffer.SetBuffer(Img11)
Global img12 = CreateImage(512,512,1) ; Local IB12:TImageBuffer = TImageBuffer.SetBuffer(Img12) 
Global img13 = CreateImage(512,512,1) ; Local IB13:TImageBuffer = TImageBuffer.SetBuffer(Img13)
Global img14 = CreateImage(512,512,1) ; Local IB14:TImageBuffer = TImageBuffer.SetBuffer(Img14) 
Global img15 = CreateImage(512,512,1) ; Local IB15:TImageBuffer = TImageBuffer.SetBuffer(Img15)
Global img16 = CreateImage(512,512,1) ; Local IB16:TImageBuffer = TImageBuffer.SetBuffer(Img16)
Global img17  = CreateImage(512,512,1) ; Local IB17:TImageBuffer = TImageBuffer.SetBuffer(Img17)
Global img18 = CreateImage(512,512,1) ; Local IB18:TImageBuffer = TImageBuffer.SetBuffer(Img18) 
Global img19 = CreateImage(512,512,1) ; Local IB19:TImageBuffer = TImageBuffer.SetBuffer(Img19)
Global img20 = CreateImage(512,512,1) ; Local IB20:TImageBuffer = TImageBuffer.SetBuffer(Img20) 
Global img21 = CreateImage(512,512,1) ; Local IB21:TImageBuffer = TImageBuffer.SetBuffer(Img21)
Global img22 = CreateImage(512,512,1) ; Local IB22:TImageBuffer = TImageBuffer.SetBuffer(Img22) 
Global img23 = CreateImage(512,512,1) ; Local IB23:TImageBuffer = TImageBuffer.SetBuffer(Img23)
Global img24 = CreateImage(512,512,1) ; Local IB24:TImageBuffer = TImageBuffer.SetBuffer(Img24)
Global img25 = CreateImage(512,512,1) ; Local IB25:TImageBuffer = TImageBuffer.SetBuffer(Img25)
Global img26 = CreateImage(512,512,1) ; Local IB26:TImageBuffer = TImageBuffer.SetBuffer(Img26) 
Global img27 = CreateImage(512,512,1) ; Local IB27:TImageBuffer = TImageBuffer.SetBuffer(Img27)
Global img28 = CreateImage(512,512,1) ; Local IB28:TImageBuffer = TImageBuffer.SetBuffer(Img28) 
Global img29 = CreateImage(512,512,1) ; Local IB29:TImageBuffer = TImageBuffer.SetBuffer(Img29)
Global img30 = CreateImage(512,512,1) ; Local IB30:TImageBuffer = TImageBuffer.SetBuffer(Img30) 
Global img31 = CreateImage(512,512,1) ; Local IB31:TImageBuffer = TImageBuffer.SetBuffer(Img31)
Global img32 = CreateImage(512,512,1) ; Local IB32:TImageBuffer = TImageBuffer.SetBuffer(Img32)
' ------------------------------- MAIN LOOP -----------------------------------

While Not MouseDown(2)

' Draw to 32 images (offscreenbuffers if you like)
IB.BindBuffer()  ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(511-50)),50+Int(Rnd(511-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END
IB3.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB3.UnBindBuffer() 'END
IB4.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB4.UnBindBuffer() 'END
IB5.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB5.UnBindBuffer() 'END
IB6.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB6.UnBindBuffer() 'END
IB7.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB7.UnBindBuffer() 'END
IB8.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB8.UnBindBuffer() 'END
IB9.BindBuffer()  ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB9.UnBindBuffer()  'END
IB10.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB10.UnBindBuffer() 'END
IB11.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB11.UnBindBuffer() 'END
IB12.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB12.UnBindBuffer() 'END
IB13.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB13.UnBindBuffer() 'END
IB14.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB14.UnBindBuffer() 'END
IB15.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB15.UnBindBuffer() 'END
IB16.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB16.UnBindBuffer() 'END
IB17.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB17.UnBindBuffer() 'END
IB18.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB18.UnBindBuffer() 'END
IB19.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB19.UnBindBuffer() 'END
IB20.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB20.UnBindBuffer() 'END
IB21.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB21.UnBindBuffer() 'END
IB22.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB22.UnBindBuffer() 'END
IB23.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB23.UnBindBuffer() 'END
IB24.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB24.UnBindBuffer() 'END
IB25.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB25.UnBindBuffer() 'END
IB26.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB26.UnBindBuffer() 'END
IB27.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB27.UnBindBuffer() 'END
IB28.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB28.UnBindBuffer() 'END
IB29.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB29.UnBindBuffer() 'END
IB30.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB30.UnBindBuffer() 'END
IB31.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB31.UnBindBuffer() 'END
IB32.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(511)),Int(Rnd(511)) ; Next ; SetColor 255,255,255 ; IB32.UnBindBuffer() 'END


' Letīs say I want to copy img (aka IB) to img8 (aka IB8), just to see it working (let's for instance copy the whole buffer to another as it is, as that's a nice thing to be able to do)
' scrap that ideas, letīs do several
IB9.BindBuffer()  ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB9.UnBindBuffer() 
IB10.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB10.UnBindBuffer() 
IB11.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB11.UnBindBuffer() 
IB12.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB12.UnBindBuffer() 
IB13.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB13.UnBindBuffer() 
IB14.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB14.UnBindBuffer() 
IB15.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB15.UnBindBuffer() 
IB16.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB16.UnBindBuffer() 
IB17.BindBuffer()  ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB17.UnBindBuffer() 
IB18.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB18.UnBindBuffer() 
IB19.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB19.UnBindBuffer() 
IB20.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB20.UnBindBuffer() 
IB21.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB21.UnBindBuffer() 
IB22.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB22.UnBindBuffer() 
IB23.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB23.UnBindBuffer() 
IB24.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB24.UnBindBuffer() 




' Something come to my mind ---------------- 
' This demo does not show that well that it is actually an mask/alpha draw thatīs happening, so you may easly layer things, from itself to another buffer or from itself to another part of itself for instance.
' So it's a bad example showing of the REAL strength that IS happening, as we draw ovals which stay in place from the next frame so when it copies/draws from one to another, you never see that it layers, as its already there.
' So you never notice that it IS masked, it just looks like an opaque copy, but itīs not. Itīs a normal (and wonderfully alphamasked) draw that happens, as you would expect with DrawImage, DrawRect and DrawSubImageRect.
' --------------

' Drawing to normal backbuffer now, nothing special

Cls

' Draw 32 512 x 512 (equal to abit more than 4 layers of 1920x1080 coverage)
DrawImage  img,xsprite*1,0	' Draw img	
DrawImage img2,xsprite*2,0	' Draw img2
DrawImage img3,xsprite*3,0	' Draw img3
DrawImage img4,xsprite*4,0	' Draw img4
DrawImage img5,xsprite*5,0	' Draw img5
DrawImage img6,xsprite*6,0	' Draw img6
DrawImage img7,xsprite*7,0	' Draw img7
DrawImage img8,xsprite*7,0	' Draw img8

DrawImage img9,xsprite*1,0	' Draw img9
DrawImage img10,xsprite*2,0	' Draw img10
DrawImage img11,xsprite*3,0	' Draw img11
DrawImage img12,xsprite*4,0	' Draw img12
DrawImage img13,xsprite*5,0	' Draw img13
DrawImage img14,xsprite*6,0	' Draw img14
DrawImage img15,xsprite*7,0	' Draw img15
DrawImage img16,xsprite*7,0	' Draw img16

DrawImage img17,xsprite*1,512' Draw img17	
DrawImage img18,xsprite*2,512' Draw img18
DrawImage img19,xsprite*3,512' Draw img19
DrawImage img20,xsprite*4,512' Draw img20
DrawImage img21,xsprite*5,512' Draw img21
DrawImage img22,xsprite*6,512' Draw img22
DrawImage img23,xsprite*7,512' Draw img23
DrawImage img24,xsprite*7,512' Draw img24

DrawImage img25,xsprite*1,512' Draw img25
DrawImage img26,xsprite*2,512' Draw img26
DrawImage img27,xsprite*3,512' Draw img27
DrawImage img28,xsprite*4,512' Draw img28
DrawImage img29,xsprite*5,512' Draw img29
DrawImage img30,xsprite*6,512' Draw img30
DrawImage img31,xsprite*7,512' Draw img31
DrawImage img32,xsprite*7,512' Draw img32


xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/8)

Delay 1 ; Flip 1
Wend

' ------------------------------- MAIN LOOP -----------------------------------

End






















Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)

Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#20]
dw817 I donīt get your code? does SETCOLOR 0,0,0 means masked/erase "color"?

Is setcolor 0,0,0 somehow connected to Alpha 0, making the ovals seethrough?

I feel so stupid right now, I'ts so small and elegant still I don't see how it works. I thought it would be just 2 layers, but you have to have SOME mean to erase from one layer.

Is that what SETCOLOR 0,0,0? does? Isnīt that just black? Does PIXMAP has some colormatching going on to make black masked?

My head spins for such a simple thing, I really have no clue how to "draw alpha" and make pixels see-through.


Casaber(Posted 2015) [#21]
Well version 1 anyways. bugs and everything.

[code]
TImageBuffer.Init(512,512) 'Same as Graphics but set to GLDriver + glewinit (or skip 32,60 for windowed version)

' Init images
Global img = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2)

IB.BindBuffer() ' draw background
For i=0 To 511 ; SetColor 0,0,i Mod 256 ; DrawLine 0,i,511,i ; Next ; SetColor 255,255,255
IB.UnBindBuffer() 'END

IB2.BindBuffer() ' draw playfield
For i=0 To 511 ; DrawOval i,Rand(511),32,32 ; Next
For i=0 To 511 ; For j=0 To 511
'If ReadPixel(pic,j,i) Then WritePixel pic,j,i,Rand(128)Shl 8|$ff000000 ' is there a normal readpixel writepixel? not plot I becuase a counterpart is needed to read, is there a snail pixelread/wirt available in some simple way?
Next ; Next
IB2.UnBindBuffer() 'END

While Not MouseDown(2)
Cls
DrawImage img,0,0 ' draw background
DrawImage img2,0,0 ' draw playfield

If MouseDown(1)
IB2.BindBuffer()
SetColor 0,0,0 ; DrawOval MouseX()-32,512-(MouseY()-32),64,64 ' mouse is not onpointov ovals are black (but itīs a start)
IB2.UnBindBuffer() 'END
SetColor 255,255,255
EndIf

Delay 1 ; Flip 1
Wend
End























Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
For j=0 To 639
If ReadPixel(pic,j,i)
WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
EndIf
Next
Next
UnlockImage(img)

Repeat
For i=0 To 479
SetColor 0,0,i Mod 256
DrawLine 0,i,639,i
Next
SetColor 255,255,255
DrawImage img,0,0
Flip
If MouseDown(1)
Cls
DrawImage img,0,0
SetColor 0,0,0
DrawOval MouseX()-32,MouseY()-32,64,64
GrabImage img,0,0
EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
Field Image:TImage
Field rb:Int[1]
Field fb:Int[1]
Field Imageframe:TGLImageframe
Field Frame:Int = 0
Field OrigX:Int
Field OrigY:Int
Field OrigW:Int
Field OrigH:Int

Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
Local IB:TImageBuffer = New TImageBuffer
IB.Image = Image ; IB.Frame = Frame ; IB.GenerateFBO() ; IB.BindBuffer()
Return IB
End Function

Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
End Function

Method GenerateFBO()
ImageFrame = TGLImageFrame(Image.frame(Frame) )
imageframe.v0 = imageframe.v1
imageframe.v1 = 0.0
Local W:Int = Image.width
Local H:Int = Image.Height
AdjustTexSize(W , H)
glGenFramebuffersEXT(1, fb )
glGenRenderbuffersEXT(1 , rb)
glBindTexture(GL_TEXTURE_2D, Imageframe.name);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ;
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)

Select status
Case GL_FRAMEBUFFER_COMPLETE_EXT
Print "all right" + " : " + Status
Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
Print "choose different formats"
Default
End
EndSelect

End Method

Method BindBuffer()
GetViewport(OrigX,OrigY,OrigW,OrigH)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0,Image.Width,Image.Width,0,-1,1
glMatrixMode GL_MODELVIEW
glViewport(0 , 0 , Image.Width , Image.Height)
glScissor 0,0, Image.Width , Image.Height
End Method

Method UnBindBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0,OrigW ,Origh,0,-1,1
glMatrixMode GL_MODELVIEW
glViewport(0 , 0 , OrigW, OrigH)
glScissor 0,0, OrigW ,OrigH
End Method

Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
glClearColor r,g,b,a
glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
End Method

Method BufferWidth:Int()
Return Image.Width
End Method

Method BufferHeight:Int()
Return Image.Height
End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
width=Pow2Size( width ) ; height=Pow2Size( height )
Repeat
Local t:Int
glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
If t Return
If width=1 And height=1 RuntimeError "Unable to calculate tex size"
If width>1 width:/2
If height>1 height:/2
Forever
End Function

Function Pow2Size:Int( n:Int )
Local t:Int=1
While t<n ; t:*2 ; Wend
Return t
End Function


dw817(Posted 2015) [#22]
Morning Casaber:

* Notice at the top I am using:
setblendmode alphablend

This means white is white and black is black, no tricks there. It also means BLACK is transparent. Now were I to use "setblendmode solidblend," BLACK would overwrite everything

Then when you click the mouse:
Cls ' clear screen to solid BLACK
DrawImage img,0,0 ' draw grass to the screen (background is not visible now)
SetColor 0,0,0 ' set to color BLACK
DrawOval MouseX()-32,MouseY()-32,64,64 ' draw a BLACK oval near the mouse
GrabImage img,0,0 ' grab the whole thing again

Just sets the color to black (transparent) before plotting an ellipse. Notice that I am plotting the 'grass' all by itself when you click the mouse so all I am doing is 'munching' out a bit of it. Grabbing the changed screen. Then continuing the program as normal.

Still ... I'm rather dismayed BlitzMAX is slowing down the more I grab an image. Reminds me very much of FLASH. When I coded in it, everything started to get slower and slower the more I made changes to the screen.

If there's a complaint dept. I'm lodging that one - and hoping for a repair to the BlitzMAX OS on its account. No reason to slow down just by grabbing a screen.


Casaber(Posted 2015) [#23]
To plot I think maybe

Function FastPlot(num%)
	glDisable GL_TEXTURE_2D	 ; glBegin GL_POINTS ; For Local p%=1 To num ; glVertex2f Rand(width),Rand(height) ; Next ;glEnd ; glEnable GL_TEXTURE_2D ; Flip
End Function


Thereīs glReadPixels, but I think you need PBO instead of VBO. Iīm not sure yet.

This are first loose ideas for fast pixel plots and reads.
PBO is too bigproject right now so. I'm abit down bc of that. I guess you could use PIXMAPS just for initiliasing stuff but itīs not a nice solution I think.

You could get descent pixel speeds to just-about being useable for realtime things (in the realm of being effecient for some things. Itīs a nice tool to have readily available thatīs what Iīm saying.

Even if you shouldnīt snort pixels, your nose starts to bleed so very quickly.
I need to solve that erasing ovals next. I feel so, so, so not bright right now. Alpha did it too me.

Butīs that's - okay.

I think this is a nice start. A days work.


Casaber(Posted 2015) [#24]
I think I should repost the code complete. I dontīlike the gray box above and it wonīt change into an actual codebox when I edit. Why I donīt know.

Letīs try a new one.

TImageBuffer.Init(512,512) 'Same as Graphics but set to GLDriver + glewinit

' Init images
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 

IB.BindBuffer() ' draw background
For i=0 To 511 ; SetColor 0,0,i Mod 256 ; DrawLine 0,i,511,i ; Next ; SetColor 255,255,255 
IB.UnBindBuffer() 'END

IB2.BindBuffer() ' draw playfield
For i=0 To 511 ; DrawOval i,Rand(511),32,32 ; Next
For i=0 To 511 ; For j=0 To 511
'If ReadPixel(pic,j,i) Then WritePixel pic,j,i,Rand(128)Shl 8|$ff000000 ' is there a normal readpixel writepixel?
Next ; Next
IB2.UnBindBuffer() 'END

While Not MouseDown(2)
Cls
DrawImage img,0,0 ' draw background
DrawImage img2,0,0 ' draw playfield

If MouseDown(1)
IB2.BindBuffer()
SetColor 0,0,0 ; DrawOval MouseX()-32,512-(MouseY()-32),64,64 ' mouse is not onpointov ovals are black (but itīs a start)
IB2.UnBindBuffer()  'END
SetColor 255,255,255
EndIf

Delay 1 ; Flip 1
Wend
End




Rem
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)

Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    Cls
    DrawImage img,0,0
    SetColor 0,0,0
    DrawOval MouseX()-32,MouseY()-32,64,64
    GrabImage img,0,0
  EndIf
Until KeyDown(32)
End
EndRem

' -------------------------------



Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#25]
ahhh so the SETMODE actually DOES something haha go figure. How could I miss that. I get those things confused. Thanks. I shall try that


Casaber(Posted 2015) [#26]
It didnīt work?

I skip the code now as it seem to be BIG boxes. And itīs pretty much the same.

I set SETBLEND ALPHABLEND at the beginning and also just before drawing (just in case). Still black?
Does SETBLEND only affects PIXMAP? it's an opengl thing no? It should work.

I really need a break from coding now, but this seem promising no?

I really enjoyed doing this. Coming closer now !


Casaber(Posted 2015) [#27]
This is where I am now anyways, so it might be worth posting I guess.
The conversion has the mouse problem, and the blackness instead of transparency problem, otherwise itīs perfect. There are two layers going on and that's great.

TImageBuffer.Init(512,512) 'Same as Graphics but set to GLDriver + glewinit
SetBlend alphablend

' Init images
Global img  = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)
Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 

IB.BindBuffer() ' draw background
For i=0 To 511 ; SetColor 0,0,i Mod 256 ; DrawLine 0,i,511,i ; Next ; SetColor 255,255,255 
IB.UnBindBuffer()

IB2.BindBuffer() ' draw playfield
For i=0 To 511 ; DrawOval i,Rand(511),32,32 ; Next
For i=0 To 511 ; For j=0 To 511
'If ReadPixel(pic,j,i) Then WritePixel pic,j,i,Rand(128)Shl 8|$ff000000 ' I guess this is 3rd problem, being able to read and write pixels, I have to decide for somthing that works well.
Next ; Next
IB2.UnBindBuffer()

While Not MouseDown(2)
Cls
DrawImage img,0,0 ' draw background
DrawImage img2,0,0 ' draw playfield

' Punch round holes out of the playfield -----------------------
If MouseDown(1)

IB2.BindBuffer()
SetBlend alphablend ; SetColor 0,0,0 ; DrawOval MouseX()-32,512-(MouseY()-32),64,64 ' should be not black and transparent ?
IB2.UnBindBuffer()

SetColor 255,255,255
EndIf
' -----------------------------------------------------------

Delay 1 ; Flip 1
Wend
End




















Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image ; 	IB.Frame = Frame ; 	IB.GenerateFBO() ; 	IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width , Height,bit,Mode ; glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
		Local W:Int = Image.width
		Local H:Int = Image.Height
		AdjustTexSize(W , H) 
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type

Function AdjustTexSize( width:Int Var,height:Int Var )
	width=Pow2Size( width ) ; height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n  ;	t:*2 ;	Wend
	Return t
End Function



Casaber(Posted 2015) [#28]
I'm starting to think that I'm actually setting things not for the actual image being drawn *from* anymore as it usually does, but for the image being drawn TO?

What the, is there a solve for this?
I think I am on the right track.


dw817(Posted 2015) [#29]
Well now if you want to do it by the dots, Casaber, you can toss your hat at the whole affair and BUILD your own 'pixel-behind' routines. Busy-busy, thinking ... Yeah, sorta like this:

CODE UPDATED 10:53pm 12-30-15 Note line before graphics.

' Grass Cutter Mark II by David W (dw817) 12-30-15
Strict
SetGraphicsDriver(GLMax2DDriver()) ' NECESSARY FOR AGGRESSIVE PIXEL READING & WRITING
Graphics 640,480
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j,x,y
Global oval:Byte[64,64]
DrawOval 0,0,64,64
pic=GrabPixmap(0,0,64,64)
For i=0 To 63
  For j=0 To 63
    If ReadPixel(pic,j,i)-$ff000000
      oval[j,i]=1
    EndIf
  Next
Next
For i=0 To 639
  DrawOval i,Rand(480),32,32
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256
    DrawLine 0,i,639,i
  Next
  SetColor 255,255,255
  DrawImage img,0,0
  Flip
  If MouseDown(1)
    pic=LockImage(img)
    For i=0 To 63
      For j=0 To 63
        If oval[j,i]
          x=MouseX()-32+j
          y=MouseY()-32+i
          If x>=0 And x<=639 And y>=0 And y<=479
            WritePixel pic,x,y,0
          EndIf
        EndIf
      Next
    Next
    UnlockImage img
  EndIf
Until KeyDown(32)
End



Casaber(Posted 2015) [#30]
Nah the readpixel writepixel was just because I loved your "grass" texture so much. And sure it would be nice to lot now and then. But for this we need the big guns,


1) pixelshader would be one I guess
2) or this (which is VBO)
3) maybe together with a PBO. Donīt even ask me about the VBO & PBO relationship I forgot all about it. I need to regain some of that.

Those where are my ideas from start and I havenīt got any new ones really. But the VBO implementation is nice.

Finally having a SETBUFFER in Blitzmax for instance was nice touch? And a working PIXMAP (well that alpha bugs the hell out of me) Same goes there; I need to gain some OpenGL knowledge.


PS should that grass go away in that weird strikey way sometimes? or is it a bug? Iīts actually nice.


dw817(Posted 2015) [#31]
Strikey way ? I'm not understanding. Basically when you hold down the button it just 'clears' out a circle. Nothing more than that.

The code I wrote above runs considerably faster but it would mean you need to use readpixel() and writepixel() to get the desired effect. I suppose I could've just captured the oval to a different pixmap() and read its pixels to see if they were valid for cutting the circle.

This just seemed the quickest way, to use a 64x64 array.


Casaber(Posted 2015) [#32]
I took a snapshot, I sometimes leaves lines behind see? I guess itīs a BlitzMAX bug. I just was curious about it. Looked kind of nice and I couldnīt see what did it in the code.



I will soon try get this worm project started I guess this it will take time to get these preparations done though. It seem a bit tricky. But itīs a good way to learn Blitzmax more deeply I think.


dw817(Posted 2015) [#33]
Hmm .... Looking ... I don't get that here. I just ran it a sec ago to see if I could recreate that. Didn't happen. Not good that the same code gets different results. Minju, the code that ran on your computer wouldn't run on mine.

Something extra to worry about. :(


dw817(Posted 2015) [#34]
I've been thinking about those lines, Casaber. I wonder if it's because I'm scanning the mouse while the circle is being drawn. Try this code to see if it clears it up. I'd like to get this to work for you:

Strict
Graphics 640,480
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j,x,y
Global oval:Byte[64,64],mx,my
DrawOval 0,0,64,64 ' draw white oval for capturing
pic=GrabPixmap(0,0,64,64)
For i=0 To 63 ' scan full 64x64 area
  For j=0 To 63
    If ReadPixel(pic,j,i)-$ff000000 ' if there is a pixel
      oval[j,i]=1 ' go ahead and mark oval array as this pixel is lit
    EndIf
  Next
Next
For i=0 To 639
  DrawOval i,Rand(480),32,32 ' simple draw white ovals across screen
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000 ' change white to 'grass'
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256 ' set a simple growing blue color flips after 256
    DrawLine 0,i,639,i ' draw it on the screen
  Next
  SetColor 255,255,255 ' be certain to go back to white for normal drawing
  DrawImage img,0,0
  Flip
  If MouseDown(1) ' you pressed the mouse
    pic=LockImage(img)
    mx=MouseX() ' record mouse X position
    my=MouseY() ' record mouse Y position
    For i=0 To 63
      For j=0 To 63
        If oval[j,i] ' if our oval array pixel is lit at this position
          x=mx-32+j
          y=my-32+i
          If x>=0 And x<=639 And y>=0 And y<=479 ' and is plotting within screen
            WritePixel pic,x,y,0 ' take out 'grass' to replace with black (transparent)
          EndIf
        EndIf
      Next
    Next
    UnlockImage img
  EndIf
Until KeyDown(32) ' keep going till you hit SPACE
End



dw817(Posted 2015) [#35]
I have some good news (for me anyways). Using graphics 640,480 causes my system to CRASH after I've erased half the screen of grass by holding the mouse down. Even if not running in DEBUG mode or using GUI App or Threaded Build.

Where does it crash ? Right on the:
DrawImage img,0,0
The error message ? A really bad one.

D3DERR: unable to create texture

I've gotten this in my coding before. So where is the good news ? I tried out your screen code thingie where you have:
timagebuffer.init()
And BAM ! That fixed it right there. It means adding a TON of code at the bottom to support your timagebuffer.init(), but my grass cutter code does work without crashing now.

For the moment I need to check Grass Cutter with:
window=CreateWindow("",deskrect[0],deskrect[1],deskrect[2],deskrect[3],,WINDOW_ACCEPTFILES)
Which is what I have in my main engine. Now, =IF= this crashes too then I have a serious problem ahead for me for any zealous read and write of pixels.

Hopefully it is just the graphics 640,480 that is causing it to crash by doing too many readpixel() and writepixel(), which is causing the drawimage to crash after -awhile.

Using your graphics technique may take out the lines you are seeing as well as I suspect the error is a nasty one that escaped even the makers of BlitzMAX and the results are unpredictable per computer.

Running it on my older computer it didn't crash but got VERY slow and started to heavily use my hard-drive I suspect for cache space, then slower, then finally crashed with the same error message above.

Your graphics seems to have fixed it. The hard-drive light still goes on as I'm erasing grass. I will experiment in depth to see if I can get it to crash now.

10:01pm

Yep, it crashes with createwindow() too, same weird error. *SIGH* Now I really will need to see what you are doing in your graphics that prevent this from happening.

I suppose if there was a way of doing this code with your graphics:
' Drop Image (modified)

Import MaxGui.Drivers
Strict
Extern "Win32"
	Function SystemParametersInfoA:Int(action:Int, param:Int, param2:Byte Ptr, winini:Int)
EndExtern
Global a,img:TImage
Global deskrect[4]
GetDesktopArea(deskrect)
Local window:TGadget
Local htmlview:TGadget
Local dropview:tgadget
Local mainview:tgadget

window=CreateWindow("",deskrect[0],deskrect[1],deskrect[2],deskrect[3],,WINDOW_ACCEPTFILES)
htmlview=CreateHTMLView(0,32,ClientWidth(window),ClientHeight(window)-32,window)
mainview=createcanvas(deskrect[0],deskrect[1]-1,deskrect[2]+2,deskrect[3],window,1)
HtmlViewGo htmlview,"http://bit.ly/1mqP51B"
SetGraphics canvasgraphics(mainview)
showgadget mainview
SetClsColor 255,0,0
SetColor 0,0,0
Repeat
  a=PollEvent()
  Cls
  DrawText "Drag Image Here",0,0
  Select EventID()
    Case event_windowaccept
      img=LoadImage(EventExtra().tostring())
      Print EventExtra().tostring()
      SetGraphics canvasgraphics(mainview)
      hidegadget htmlview
      SetColor 255,255,255
      Repeat
        a=PollEvent()
        DrawImage img,0,0
        Flip
      Until KeyDown(32)
      End
  End Select
  Flip
Forever

Function getdesktoparea(lprect:Int Ptr)
	systemparametersinfoa(spi_getworkarea,0,lprect,0)
End Function


That would solve this little problem.
Oh, if you want to experiment with this, click on one of the images until only the image remains. Then drag it to the top. It will be copied so BlitzMAX can work with it.

I plan to implement this into the RPG engine, obviously using a different website that houses my RPG add-ons, but I'm not liking that I have to use CreateWindow() to build it.


dw817(Posted 2015) [#36]

G O T C H A !

What was it you said ? Something so small but yet eluding.

Typing out your code to inject into my Grass Cutter is a bit like inserting a nuclear detonator to poison a mouse. Likely it is incredibly effective for what you designed it for, but I just needed to know why your graphics wouldn't crash strangely.

And, it was something - very small - and very eluding.
SetGraphicsDriver(GLMax2DDriver())
I just needed to have this before my usual GRAPHICS 640,480 and everything works fine. Not -entirely- sure why. The HELP file just says it is a Max2D driver. Well, no complaints there, all my work is 2D. And it no longer tries to cache the image to the hard-drive. Runs better than ever !

A real test will be to check with the upstairs computer (Windows XP) and see if it runs super slow and throttles the hard-drive again - or will it run much better ? BRB ...
Doesn't run much faster, it's not a very speedy computer, but no throttling the hard-drive like before. Definitely fixed it.

Check to see if this fixes the strange lines that appeared for you too, Casaber.

And ? Guess what ? My =ORIGINAL= smaller code is now just as fast as the secondary (at least on my main computer). That's right, the one that grabs the whole image each time. Here's the final of it:
'    ______________________________________
'   //                                   //
'  //  Fast Grass Cutter v0.023         //
' //    Written by David W - 12/30/15  //
'//___________________________________//
Strict
SeedRnd MilliSecs() ' True random results each time
SetGraphicsDriver(GLMax2DDriver()) ' NECESSARY FOR AGGRESSIVE PIXEL READING & WRITING
Graphics 640,480
SetBlend alphablend ' Allows BLACK to be transparent when plotted
Global img:TImage=CreateImage(640,480),pic:TPixmap,i,j
For i=0 To 639
  DrawOval i,Rand(480),32,32 ' simple draw white ovals across screen
Next
GrabImage img,0,0
pic=LockImage(img)
For i=0 To 479
  For j=0 To 639
    If ReadPixel(pic,j,i)
      WritePixel pic,j,i,Rand(128)Shl 8|$ff000000 ' change ovals to 'grass'
    EndIf
  Next
Next
UnlockImage(img)
Repeat
  For i=0 To 479
    SetColor 0,0,i Mod 256 ' set a simple growing blue color flips after 256
    DrawLine 0,i,639,i ' draw it on the screen
  Next
  SetColor 255,255,255 ' be certain to go back to white for normal drawing
  DrawImage img,0,0 ' INSERT the grass on top of the blue design
  Flip
  If MouseDown(1) ' if you hold the mouse down
    Cls ' clear screen to black (important)
    DrawImage img,0,0 ' draw ONLY the grass now
    SetColor 0,0,0 ' set color to BLACK (also transparent)
    DrawOval MouseX()-32,MouseY()-32,64,64 ' draw a circle at mouse position
    GrabImage img,0,0 ' grab the image back again
  EndIf
Until KeyDown(32) ' repeat until you hit SPACEBAR



Casaber(Posted 2015) [#37]
Great news !! Ya.. I was quick aswell to debug the mouse coordinates after some sleep just before I read to see that you had done it to so I donīt have to post that haha

I noticed it got worse when I movied the mouse around so that was a dead giveaway. I didnīt notice that the first time around and the fact that I assumed it worked fine all the way on your side made me overlook it. I can confirm it works here aswell now. No output on different machines, no bugs in the grass.

About the graphics command, actually my guess would have been to do what you did, and I think GUI uses the same graphics driver/mode, I guess it could work with the right OpenGL command aswell. But Iīm not good at explaining ecatly WHY it works yet. If Blitzmax graphics commands has a strong stable side, I hope it is the openGL one. And not DirectX which I think it still defaults to and thatīs where you got your error for some reason?

For me opengl in new Windows is the way to go fullscreen is absolutelty smooth, and windowed mode are the most acceptable Iīve seen in any Windows ever. So starting to use that graphics mode/driver
I think was a good move even if you donīt know what caused this particular error.

No luck on progress on the Worms Iīm afraid. I will be sometime in 2016 haha.

Wishing you a Happy New year !!


Casaber(Posted 2015) [#38]
Also, I like that new version youīve got, very elegant. Great stuff !!

I must get my head around how to get that same "alpha erasing mode" in my code. Thatīs my biggest problem now.


Casaber(Posted 2015) [#39]
I would love to know if my code is worth building upon to be inspired to continue with it.

Could you try this on your machine and tell me if you experience good speed? If this runs smooth on every machine I would need to, I would be so thrilled.
Itīs a pretty harsch test actually, but I have high hopes that it works in alot of places. My two machines gave me a really smooth experience with this code.

HideMouse ; TImageBuffer.Init(1920,1080,32,60) ; SetBlend(MASKBLEND)

'
' Test # 5
'
' Welcome... to hard-coded-mania
'
' One would love arraying those img's it hurts to see this repetition, but's that's for another day.
'

' Init images
Global img = CreateImage(512,512,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) ; Global img2 = CreateImage(512,512,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2) 
Global img3 = CreateImage(512,512,1) ; Local IB3:TImageBuffer = TImageBuffer.SetBuffer(Img3) ; Global img4 = CreateImage(512,512,1) ; Local IB4:TImageBuffer = TImageBuffer.SetBuffer(Img4) 
Global img5 = CreateImage(512,512,1) ; Local IB5:TImageBuffer = TImageBuffer.SetBuffer(Img5) ; Global img6 = CreateImage(512,512,1) ; Local IB6:TImageBuffer = TImageBuffer.SetBuffer(Img6) 
Global img7 = CreateImage(512,512,1) ; Local IB7:TImageBuffer = TImageBuffer.SetBuffer(Img7) ; Global img8 = CreateImage(512,512,1) ; Local IB8:TImageBuffer = TImageBuffer.SetBuffer(Img8)
Global img9 = CreateImage(512,512,1) ; Local IB9:TImageBuffer = TImageBuffer.SetBuffer(Img9) ; Global img10 = CreateImage(512,512,1) ; Local IB10:TImageBuffer = TImageBuffer.SetBuffer(Img10) 
Global img11 = CreateImage(512,512,1) ; Local IB11:TImageBuffer = TImageBuffer.SetBuffer(Img11) ; Global img12 = CreateImage(512,512,1) ; Local IB12:TImageBuffer = TImageBuffer.SetBuffer(Img12) 
Global img13 = CreateImage(512,512,1) ; Local IB13:TImageBuffer = TImageBuffer.SetBuffer(Img13) ; Global img14 = CreateImage(512,512,1) ; Local IB14:TImageBuffer = TImageBuffer.SetBuffer(Img14) 
Global img15 = CreateImage(512,512,1) ; Local IB15:TImageBuffer = TImageBuffer.SetBuffer(Img15) ; Global img16 = CreateImage(512,512,1) ; Local IB16:TImageBuffer = TImageBuffer.SetBuffer(Img16)
Global img17 = CreateImage(512,512,1) ; Local IB17:TImageBuffer = TImageBuffer.SetBuffer(Img17) ; Global img18 = CreateImage(512,512,1) ; Local IB18:TImageBuffer = TImageBuffer.SetBuffer(Img18) 
Global img19 = CreateImage(512,512,1) ; Local IB19:TImageBuffer = TImageBuffer.SetBuffer(Img19) ; Global img20 = CreateImage(512,512,1) ; Local IB20:TImageBuffer = TImageBuffer.SetBuffer(Img20) 
Global img21 = CreateImage(512,512,1) ; Local IB21:TImageBuffer = TImageBuffer.SetBuffer(Img21) ; Global img22 = CreateImage(512,512,1) ; Local IB22:TImageBuffer = TImageBuffer.SetBuffer(Img22) 
Global img23 = CreateImage(512,512,1) ; Local IB23:TImageBuffer = TImageBuffer.SetBuffer(Img23) ; Global img24 = CreateImage(512,512,1) ; Local IB24:TImageBuffer = TImageBuffer.SetBuffer(Img24)
Global img25 = CreateImage(512,512,1) ; Local IB25:TImageBuffer = TImageBuffer.SetBuffer(Img25) ; Global img26 = CreateImage(512,512,1) ; Local IB26:TImageBuffer = TImageBuffer.SetBuffer(Img26) 
Global img27 = CreateImage(512,512,1) ; Local IB27:TImageBuffer = TImageBuffer.SetBuffer(Img27) ; Global img28 = CreateImage(512,512,1) ; Local IB28:TImageBuffer = TImageBuffer.SetBuffer(Img28) 
Global img29 = CreateImage(512,512,1) ; Local IB29:TImageBuffer = TImageBuffer.SetBuffer(Img29) ; Global img30 = CreateImage(512,512,1) ; Local IB30:TImageBuffer = TImageBuffer.SetBuffer(Img30) 
Global img31 = CreateImage(512,512,1) ; Local IB31:TImageBuffer = TImageBuffer.SetBuffer(Img31) ; Global img32 = CreateImage(512,512,1) ; Local IB32:TImageBuffer = TImageBuffer.SetBuffer(Img32)

' ----------------------------------------------------------------------------------------

While Not MouseDown(2)

' Draw to 32 images (offscreenbuffers if you like)
IB.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(511-50)),50+Int(Rnd(511-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END
IB3.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB3.UnBindBuffer() 'END
IB4.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB4.UnBindBuffer() 'END
IB5.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB5.UnBindBuffer() 'END
IB6.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB6.UnBindBuffer() 'END
IB7.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB7.UnBindBuffer() 'END
IB8.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB8.UnBindBuffer() 'END
IB9.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB9.UnBindBuffer()  'END
IB10.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB10.UnBindBuffer() 'END
IB11.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB11.UnBindBuffer() 'END
IB12.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB12.UnBindBuffer() 'END
IB13.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB13.UnBindBuffer() 'END
IB14.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB14.UnBindBuffer() 'END
IB15.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB15.UnBindBuffer() 'END
IB16.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB16.UnBindBuffer() 'END
IB17.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB17.UnBindBuffer() 'END
IB18.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB18.UnBindBuffer() 'END
IB19.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB19.UnBindBuffer() 'END
IB20.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB20.UnBindBuffer() 'END
IB21.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB21.UnBindBuffer() 'END
IB22.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB22.UnBindBuffer() 'END
IB23.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB23.UnBindBuffer() 'END
IB24.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB24.UnBindBuffer() 'END
IB25.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB25.UnBindBuffer() 'END
IB26.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB26.UnBindBuffer() 'END
IB27.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB27.UnBindBuffer() 'END
IB28.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB28.UnBindBuffer() 'END
IB29.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB29.UnBindBuffer() 'END
IB30.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB30.UnBindBuffer() 'END
IB31.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB31.UnBindBuffer() 'END
IB32.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB32.UnBindBuffer() 'END

IB9.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB9.UnBindBuffer() ; IB10.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB10.UnBindBuffer() 
IB11.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB11.UnBindBuffer() ; IB12.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB12.UnBindBuffer() 
IB13.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB13.UnBindBuffer() ; IB14.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB14.UnBindBuffer() 
IB15.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB15.UnBindBuffer() ; IB16.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB16.UnBindBuffer() 
IB17.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB17.UnBindBuffer() ; IB18.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB18.UnBindBuffer() 
IB19.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB19.UnBindBuffer() ; IB20.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB20.UnBindBuffer() 
IB21.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB21.UnBindBuffer() ; IB22.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB22.UnBindBuffer() 
IB23.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB23.UnBindBuffer() ; IB24.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB24.UnBindBuffer() 

Cls

' Draw 32 512 x 512 (equal to abit more than 4 layers of 1920x1080 coverage)
DrawImage img,xsprite*1,0 ; DrawImage img2,xsprite*2,0 ; DrawImage img3,xsprite*3,0 ; DrawImage img4,xsprite*4,0
DrawImage img5,xsprite*5,0 ; DrawImage img6,xsprite*6,0 ; DrawImage img7,xsprite*7,0 ; DrawImage img8,xsprite*7,0	
DrawImage img9,xsprite*1,0 ; DrawImage img10,xsprite*2,0 ; DrawImage img11,xsprite*3,0 ; DrawImage img12,xsprite*4,0
DrawImage img13,xsprite*5,0 ; DrawImage img14,xsprite*6,0 ; DrawImage img15,xsprite*7,0 ; DrawImage img16,xsprite*7,0	
DrawImage img17,xsprite*1,512 ; DrawImage img18,xsprite*2,512 ; DrawImage img19,xsprite*3,512 ; DrawImage img20,xsprite*4,512
DrawImage img21,xsprite*5,512 ; DrawImage img22,xsprite*6,512 ; DrawImage img23,xsprite*7,512 ; DrawImage img24,xsprite*7,512
DrawImage img25,xsprite*1,512 ; DrawImage img26,xsprite*2,512 ; DrawImage img27,xsprite*3,512 ; DrawImage img28,xsprite*4,512
DrawImage img29,xsprite*5,512 ; DrawImage img30,xsprite*6,512 ; DrawImage img31,xsprite*7,512 ; DrawImage img32,xsprite*7,512

xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/8)
Delay 1 ; Flip 1
Wend
End

' ----------------------------------------------------------------------------------------

Type TImageBuffer
Field Image:TImage ; Field rb:Int[1] ; Field fb:Int[1] ; Field Imageframe:TGLImageframe
Field Frame:Int = 0 ; Field OrigX:Int ; Field OrigY:Int ; Field OrigW:Int ; Field OrigH:Int

Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0)
Local IB:TImageBuffer = New TImageBuffer ; IB.Image = Image ; IB.Frame = Frame ; IB.GenerateFBO() ; IB.BindBuffer() ; Return IB
End Function
	
Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
SetGraphicsDriver(GLMax2DDriver()) ; Graphics Width, Height, bit, Mode ; glewInit()
End Function
	
Method GenerateFBO()
ImageFrame = TGLImageFrame(Image.frame(Frame) ) ; imageframe.v0 = imageframe.v1 ; imageframe.v1 = 0.0
Local W:Int = Image.width ; Local H:Int = Image.Height ; AdjustTexSize(W, H) ; glGenFramebuffersEXT(1, fb)
glGenRenderbuffersEXT(1, rb) ; glBindTexture(GL_TEXTURE_2D, Imageframe.name) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]) ; glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H) 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb[0])
Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
End Method
	
Method BindBuffer()
GetViewport(OrigX,OrigY,OrigW,OrigH) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0, Image.Width,Image.Width, 0, -1, 1 ; glMatrixMode GL_MODELVIEW
glViewport(0, 0, Image.Width, Image.Height) ; glScissor 0, 0, Image.Width, Image.Height
End Method
	
Method UnBindBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) ; glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,OrigW, Origh, 0, -1, 1
glMatrixMode GL_MODELVIEW ; glViewport(0, 0, OrigW, OrigH) ; glScissor 0, 0, OrigW, OrigH
End Method

End Type

Function AdjustTexSize(width:Int Var,height:Int Var)
width=Pow2Size(width) ; height=Pow2Size(height)
Repeat
Local t:Int ; glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
If t Return
If width>1 width:/2
If height>1 height:/2
Forever
End Function

Function Pow2Size:Int(n:Int)
Local t:Int=1 ; While t<n ; 	t:*2; Wend ; Return t
End Function



Casaber(Posted 2015) [#40]
Hereīs a good reference for anyone who wants to try this method in their games.

Itīs a good entry point to trying to grasp how things works and how to use it. I tried to keep it smallish.

' Test # 3
'
' aka finally-a-SETBUFFER-working-in-BlitzMAX
'
' Also, showing that alpha truly exists (a relief)
'
' When pixelread, pixelwrite, and PNG save is implemented this could also be used instead of PIXMAP in all occasions. You then draw directly onto things that you meant to grab from in the first place. 

' Fullscreen
HideMouse ; SetGraphicsDriver(GLMax2DDriver()) ; Graphics 1920,1080,32,60 ; glewInit() ; SetBlend(MASKBLEND)

' Init images, letīs make two
Global img = CreateImage(512,512,,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) ; Global img2 = CreateImage(512,512,,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2)

' Main loop ---------------------------------------------------------------------------

While Not MouseDown(2)

' Draw to the images (offscreenbuffers if you like)
IB.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(512-50)),50+Int(Rnd(512-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; Plot Int(Rnd(512)),Int(Rnd(512)) ; Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END

' Now we have two images to play with, one filled with dots, one filled with ovals
' letīs copy the one with the ovals onto the one with the dots.

' Draw from image img2 to img, letīs copy the whole thing, transfer every pixel
IB2.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB2.UnBindBuffer()

Cls

' Letīs draw both images onto the backbuffer so we may see what we have going on.
' One should have ovals only, And one should have the ovals And itīs pixels.
'
DrawImage img,xsprite*2,0 ; DrawImage img2,xsprite*3,0 ; xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/4)

' Letīs add two more below these two, we could draw again but instead use DrawSubImageRect, just To show itīs good to use everywhere. Say you want To draw half img onto the screen.
DrawSubImageRect img,xsprite*3, 512, 512, 256,0 ,0, 512, 256

' We may stretch things too, letīs double the size (itīs just one way to fake resolutions cheaply using HW acc, it's not hard to come by today but itīs stuck in here, ready to be used) 
' Offscreen buffers begs for these kind of tricks
DrawSubImageRect img2,xsprite*4, 512, 512, 512,0 ,0, 256, 256

' You could rotate and scale using normal commands of course, here's a swinging New years eve bell made out of img2 (dig out your creative interpretation skills) 
SetRotation Sin(swing) * 50 ; swing = swing + 1 ; swing = swing Mod 360
DrawImage img2,xsprite*2,512
SetRotation 0

Delay 1 ; Flip 1
Wend
End
' ----------------------------------------------------------------------------------------

Type TImageBuffer
Field Image:TImage ; Field rb:Int[1] ; Field fb:Int[1] ; Field Imageframe:TGLImageframe
Field Frame:Int = 0 ; Field OrigX:Int ; Field OrigY:Int ; Field OrigW:Int ; Field OrigH:Int

Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0)
Local IB:TImageBuffer = New TImageBuffer ; IB.Image = Image ; IB.Frame = Frame ; IB.GenerateFBO() ; IB.BindBuffer() ; Return IB
End Function
	
Method GenerateFBO()
ImageFrame = TGLImageFrame(Image.frame(Frame) ) ; imageframe.v0 = imageframe.v1 ; imageframe.v1 = 0.0
Local W:Int = Image.width ; Local H:Int = Image.Height ; AdjustTexSize(W, H) ; glGenFramebuffersEXT(1, fb)
glGenRenderbuffersEXT(1, rb) ; glBindTexture(GL_TEXTURE_2D, Imageframe.name) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]) ; glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H) 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb[0])
Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
End Method
	
Method BindBuffer()
GetViewport(OrigX,OrigY,OrigW,OrigH) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0, Image.Width,Image.Width, 0, -1, 1 ; glMatrixMode GL_MODELVIEW
glViewport(0, 0, Image.Width, Image.Height) ; glScissor 0, 0, Image.Width, Image.Height
End Method
	
Method UnBindBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) ; glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,OrigW, Origh, 0, -1, 1
glMatrixMode GL_MODELVIEW ; glViewport(0, 0, OrigW, OrigH) ; glScissor 0, 0, OrigW, OrigH
End Method

End Type

Function AdjustTexSize(width:Int Var,height:Int Var)
width=Pow2Size(width) ; height=Pow2Size(height)
Repeat
Local t:Int ; glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
If t Return
If width>1 width:/2
If height>1 height:/2
Forever
End Function

Function Pow2Size:Int(n:Int)
Local t:Int=1 ; While t<n ; t:*2; Wend ; Return t
End Function



Casaber(Posted 2015) [#41]
Here's one with a text without using text command (donīt rely on it but It runs on all my versions and variations old and new, despite it's old)
This one has a personal mess attached to it, but it's neat if you can overlook all that.

' fix why does graphics gets transparent if you draw in backbuffer
' fix simple init
' fix not end
' fix inv y
' bug in demo or why do they change appearence with time in that weak layering effect?
' When pixelread, pixelwrite, and PNG save is implemented then it may be used to replace PIXMAP all the way aswell.

' Best solutions would probably be; This VBO, PBO, Multitexture, or just a pixelshader (which bunched everything under one roof and would probably give zero drawbacks, only advantages and added flexibility).

Rem
One easy Method might be multitexture
tex0 = dynamic RGB texture, from video stream
tex1 = static RGBA mask, RGB as white And A as your alpha
Using (tex0 blend tex1) with classic blending should work. I think the Default operator of the multitexture setup is blending.

the Default operator is blending, And all you have To do To set up is:
glActiveTexture(GL_TEXTURE0)
' bind And set up image texture; does Not need alpha channel in internal format
glActiveTexture(GL_TEXTURE1)
' bind And set up alpha texture; GL_ALPHA internal, GL_ALPHA format.
The mask texture doesn't need any color components it can be entirely alpha values, and when rendering:
glActiveTexture(GL_TEXTURE0)
glEnable(GL_TEXTURE_2D ' or similiar
glActiveTexture(GL_TEXTURE1)
glEnable(GL_TEXTURE_2D)
And do glMultiTexCoord(GL_TEXTURE0 And GL_TEXTURE1, ...) For the texture coordinates and it magically works.
EndRem

' SetMaskColor doesn't work with images that already have an alpha channel present, remove the alpha channel first.
' Local Image:TImage = LoadImage(ConvertPixmap(LoadPixmap("MyImage.png"),PF_RGB888))

' Test # 3
'
' aka finally-a-SETBUFFER-working-in-BlitzMAX
'
' Also, showing that alpha truly exists (a relief)
'
'Framework BRL.GLMax2D
'Import BRL.PNGLoader
'AutoImageFlags 0 ; Graphics 400,300,0 ; SetClsColor 100,200,100
'i=LoadImage("tree.png",MASKEDIMAGE) ' creates alphachannel based on setmaskcolor (if the image has an alphachannel (32bit instead of 24bit) already nothing happens)

' freetype
' cairo

' Code using BlitzMax internals which are sensitive (in that they could change with time)

' Fullscreen
HideMouse ; SetGraphicsDriver(GLMax2DDriver()) ; Graphics 1920,1080,32,60 ; glewInit() ; SetBlend(MASKBLEND)

' Prepare to write some text (works for Mac and PC)
SetImageFont(LoadImageFont("Default.ttf", 32)) ; Global font:timagefont = GetImageFont() ; Global g:TMax2DGraphics = tmax2dgraphics.Current()

' Init images, letīs make two
Global img = CreateImage(512,512,,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) ; Global img2 = CreateImage(512,512,,1) ; Local IB2:TImageBuffer = TImageBuffer.SetBuffer(Img2)
SetMaskColor 0,0,0 ; SetBlend(MASKBLEND)

' Main loop ---------------------------------------------------------------------------

' filled box
' filled polygon
' pixels
' lines (maybe polygon)

While Not MouseDown(2)

' Draw to the images (offscreenbuffers if you like)
IB.BindBuffer() ; For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(512-50)),50+Int(Rnd(512-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ; IB.UnBindBuffer()  'END
IB2.BindBuffer() ; For temp=0 To 100 
SetColor Rnd(255),Rnd(255),Rnd(255) '; Plot Int(Rnd(512)),Int(Rnd(512)) ; 

'glDrawPixels
' simulate an overlay with the previous method, using alpha test. enable GL_ALPHA_TEST, set alphafunc to (GL_GREATER,0.5), and create a RGBA texture as described above (1024x1024 for 800x600, etc).
' Then, For each visible pixel, draw the pixel in the texture And set its alpha To 255, While undrawn pixels could be set To alpha 0.
fastplot(Rnd(255),Rnd(255)) 'About twice the speed as plot, and more if you batch pixels but we donīt do that here, one pixel at a time only for now

Next ; SetColor 255,255,255 ; IB2.UnBindBuffer() 'END

' Now we have two images to play with, one filled with dots, one filled with ovals
' letīs copy the one with the ovals onto the one with the dots.

' Draw from image img2 to img, letīs copy the whole thing, transfer every pixel
IB2.BindBuffer() ; DrawSubImageRect img,0,512-0,512,-512, 0,0,512,512 ; IB2.UnBindBuffer()

Cls

'For temp=0 To 100 ; SetColor Rnd(255),Rnd(255),Rnd(255) ; DrawOval 50+Int(Rnd(512-50)),50+Int(Rnd(512-50)),Int(Rnd(50)),Int(Rnd(50)) ; Next ; SetColor 255,255,255 ;

' Letīs draw both images onto the backbuffer so we may see what we have going on.
' One should have ovals only, And one should have the ovals And itīs pixels.
'
DrawImage img,xsprite*2,0 ; DrawImage img2,xsprite*3,0 ; xsprite = xsprite + 1 ; xsprite = xsprite Mod ((1920-512)/4)

' Letīs add two more below these two, we could draw again but instead use DrawSubImageRect, just To show itīs good to use everywhere. Say you want To draw half img onto the screen.
DrawSubImageRect img,xsprite*3, 512, 512, 256,0 ,0, 512, 256

' We may stretch things too, letīs double the size (itīs just one way to fake resolutions cheaply using HW acc, it's not hard to come by today but itīs stuck in here, ready to be used) 
' Offscreen buffers begs for these kind of tricks
DrawSubImageRect img2,xsprite*4, 512, 512, 512,0 ,0, 256, 256

' You could rotate and scale using normal commands of course, here's a swinging New years eve bell made out of img2 (dig out your creative interpretation skills) 
SetRotation Sin(swing) * 50 ; swing = swing + 1 ; swing = swing Mod 360
DrawImage img2,xsprite*2,512
SetRotation 0 ; SetScale 1,1

' Draw 10.000 lines, each line made out of 512 pixels. Itīs a set template for an average line. 
' This is a good amount of lines to create vVctor games (gow will come next)
'For temp=1 To 10000 ; DrawLine 0,0,511,511 ; Next

DrawThickLine(100,100,511,511,5)
draw("Not a terrible slow text",300,300)

Delay 1 ; Flip 1
Wend
End
' ----------------------------------------------------------------------------------------

Type TImageBuffer
Field Image:TImage ; Field rb:Int[1] ; Field fb:Int[1] ; Field Imageframe:TGLImageframe
Field Frame:Int = 0 ; Field OrigX:Int ; Field OrigY:Int ; Field OrigW:Int ; Field OrigH:Int

Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0)
Local IB:TImageBuffer = New TImageBuffer ; IB.Image = Image ; IB.Frame = Frame ; IB.GenerateFBO() ; IB.BindBuffer() ; Return IB
End Function

Method GenerateFBO()
ImageFrame = TGLImageFrame(Image.frame(Frame) ) ; imageframe.v0 = imageframe.v1 ; imageframe.v1 = 0.0
Local W:Int = Image.width ; Local H:Int = Image.Height ; AdjustTexSize(W, H) ; glGenFramebuffersEXT(1, fb)
glGenRenderbuffersEXT(1, rb) ; glBindTexture(GL_TEXTURE_2D, Imageframe.name) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]) ; glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H) 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb[0])
Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
End Method
	
Method BindBuffer()
GetViewport(OrigX,OrigY,OrigW,OrigH) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0, Image.Width,Image.Width, 0, -1, 1 ; glMatrixMode GL_MODELVIEW
glViewport(0, 0, Image.Width, Image.Height) ; glScissor 0, 0, Image.Width, Image.Height
End Method
	
Method UnBindBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) ; glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,OrigW, Origh, 0, -1, 1
glMatrixMode GL_MODELVIEW ; glViewport(0, 0, OrigW, OrigH) ; glScissor 0, 0, OrigW, OrigH
End Method

End Type

Function AdjustTexSize(width:Int Var,height:Int Var)
width=Pow2Size(width) ; height=Pow2Size(height)
Repeat
Local t:Int ; glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
If t Return
If width>1 width:/2
If height>1 height:/2
Forever
End Function

Function Pow2Size:Int(n:Int)
Local t:Int=1 ; While t<n ; t:*2; Wend ; Return t
End Function

Function Draw(text$,x#,y#) ' routine that uses internals of BlitzMax (that might change). It doesn't use any atlas, but it makes text into regular imagedrawing which is good for testing as it at brings up the speed of "not interfering".
For Local i% = 0 Until text.length
Local n%=font.CharToGlyph(text[i])
If n < 0 Then Continue
Local glyph:TImageGlyph=font.LoadGlyph(n)
If glyph._image Then Local tx#=glyph._x*g.tform_ix+glyph._y*g.tform_iy ; Local ty#=glyph._x*g.tform_jx+glyph._y*g.tform_jy ; DrawImage glyph._image,x+tx,y+ty
x = x + glyph._advance*g.tform_ix ; y = y + glyph._advance*g.tform_jx
Next
End Function

Function DrawThickLine(x1#,y1#,x2#,y2#,thickness#) ' no smoothness, and no glow
rot#=GetRotation() ; dx# = x2-x1 ; dy# = y2-y1 ; length# = Sqr(dx*dx+dy*dy) ; an# = ATan2(dy,dx)
SetRotation an ; DrawRect x1+Sin(an)*thickness/2,y1-Cos(an)*thickness/2,length,thickness ; SetRotation rot
End Function

Function FastPlot(x,y)
glDisable GL_TEXTURE_2D	 ; glBegin GL_POINTS
glVertex2f x,y ' Here we should plot as many pixels at once as we could, so an array would be a great idea as parameter (ala polygon)
glEnd ; glEnable GL_TEXTURE_2D
End Function



dw817(Posted 2015) [#42]
Getting to these in reverse order, Casaber.

Your DrawThickLine is a marvel of coding, however BlitzMAX has a thickness function to assist with drawing lines:
Function drawthickline2(x1,y1,x2,y2,t)
SetLineWidth t
DrawLine x1,y1,x2,y2
SetLineWidth 1
EndFunction
As for the FastPlot routine, I tried it out in simple code:
SetGraphicsDriver(GLMax2DDriver())
Graphics 640,480
Repeat
  For i=0 To 479
    For j=0 To 639
  SetColor Rand(256),Rand(256),Rand(256)
'      fastplot j,i
      Plot j,i
    Next
  Next
  Flip
Until KeyDown(32)

Function FastPlot(x,y)
glDisable GL_TEXTURE_2D	 ; glBegin GL_POINTS
glVertex2f x,y ' Here we should plot as many pixels at once as we could, so an array would be a great idea as parameter (ala polygon)
glEnd ; glEnable GL_TEXTURE_2D
End Function
Checking plot() with fastplot(), it is definitely not faster, not for me in this example anyways.

Looking at the draw() command for plotting text. It APPEARS to be just as strong and powerful as the drawtext(), a command already available in BlitzMAX.

Your Post #39 runs very fast indeed.

Now looking at the size and scope of your code I am wondering if you are drawing lines, ellipses, and points directly to a tpixmap or timage, and if so, can you isolate that code and show me how you are doing this, please ?

Perhaps a simple program that draws ellipses straight into a tpixmap or timage.


Casaber(Posted 2015) [#43]
Good to know the example works great for your machine aswell.

Sure I could give you the simpler example for drawing a line to the Timage. Donīt mind the functions it's opengl magic. I need time to understand opengl better first. This is my personal exprimental for doing just that. But ya.. drawing to an Image i can show. Here


SetGraphicsDriver(GLMax2DDriver()) ; Graphics 800,600 ; glewInit() ; SetBlend(MASKBLEND)

' Init image
Global img = CreateImage(512,512,,1) ; Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img)

' Draw red oval to image img (Timage)
IB.BindBuffer() ; SetColor 0,255,0 ; Drawline 100,100,245,255 ; SetColor 255,255,255 ; IB.UnBindBuffer()

Cls
DrawImage img,0,0 ' draw it on the screen

Flip 1
WaitKey
End

' ----------------------------------------------------------------------------------------

Type TImageBuffer
Field Image:TImage ; Field rb:Int[1] ; Field fb:Int[1] ; Field Imageframe:TGLImageframe
Field Frame:Int = 0 ; Field OrigX:Int ; Field OrigY:Int ; Field OrigW:Int ; Field OrigH:Int

Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0)
Local IB:TImageBuffer = New TImageBuffer ; IB.Image = Image ; IB.Frame = Frame ; IB.GenerateFBO() ; IB.BindBuffer() ; Return IB
End Function
	
Method GenerateFBO()
ImageFrame = TGLImageFrame(Image.frame(Frame) ) ; imageframe.v0 = imageframe.v1 ; imageframe.v1 = 0.0
Local W:Int = Image.width ; Local H:Int = Image.Height ; AdjustTexSize(W, H) ; glGenFramebuffersEXT(1, fb)
glGenRenderbuffersEXT(1, rb) ; glBindTexture(GL_TEXTURE_2D, Imageframe.name) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Imageframe.name, 0)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]) ; glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H) 
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb[0])
Local status:Int = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
End Method
	
Method BindBuffer()
GetViewport(OrigX,OrigY,OrigW,OrigH) ; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb[0])
glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0, Image.Width,Image.Width, 0, -1, 1 ; glMatrixMode GL_MODELVIEW
glViewport(0, 0, Image.Width, Image.Height) ; glScissor 0, 0, Image.Width, Image.Height
End Method
	
Method UnBindBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0) ; glMatrixMode GL_PROJECTION ; glLoadIdentity ; glOrtho 0,OrigW, Origh, 0, -1, 1
glMatrixMode GL_MODELVIEW ; glViewport(0, 0, OrigW, OrigH) ; glScissor 0, 0, OrigW, OrigH
End Method

End Type

Function AdjustTexSize(width:Int Var,height:Int Var)
width=Pow2Size(width) ; height=Pow2Size(height)
Repeat
Local t:Int ; glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
If t Return
If width>1 width:/2
If height>1 height:/2
Forever
End Function

Function Pow2Size:Int(n:Int)
Local t:Int=1 ; While t<n ; t:*2; Wend ; Return t
End Function



Kryzon(Posted 2015) [#44]
Try using the [codebox] tag in your forum posts, it creates a scrollable area that compacts code. Less scrolling for the people reading.


Casaber(Posted 2015) [#45]
One of the things you need to adjust is, for some reason VBOīs (as it's called) easly get things upside down. I need to inject some instructions to adjust that.

So things are upside down (Y coordinate 0 is actually at the bottom). Other than that thereīs nothing to say about it really. You could just paint as usual.

I'm still struggling with getting those alpha modes working. I would love to have those fully working.
The thing is, I think it does work, but youīre actually set the mode for the TIMAGE itself instead of um it's some kind of source-and-destination-both-being-TIMAGEīs problem that messes things up my guess is, I could be wrong.
it messes up standard commands, they get overriden.

So this needs to be corrected.

Those two things are on my top list now.


Casaber(Posted 2015) [#46]
Kryzon scrollable boxes. Thanks.


Casaber(Posted 2015) [#47]
Red oval is green line. I guess Itīs a surprise party.
Iīm abit messed up I should get going.


Wishing a
Happy new year !!


Casaber(Posted 2015) [#48]
Change

CreateImage(512,512,,1)

to

CreateImage(800,600,,1)

if you like.

Then you would have a Timage which would be the perfect offscreenbuffer for that particular windowsize.
If you happen to want to use your TIMAGE as an offlinebuffer. This would be a good usage of it.

512x512 isnīt a fixed or maximum size, It's a personal preference that I use that alot.

So this is a image, itīs a TIMAGE, itīs offlinebuffer, itīs a spritesheet, itīs a atlas, itīs a texture. Dear child have many many many MANY names.

Thatīs why I got one name.


dw817(Posted 2015) [#49]
Alright Casaber, lemme spear-a-mint here for a sec ... Will try the (codebox) Kryzon, thanks.


I fixed your rotation and image flipping problem, Casaber. I just wish there was an easier way to write to a TIMAGE rather than have all that code.

In GFA to create a 'timage' you could draw to, it was:
newdc=MEMDC(_DC(1))
bmpdc=CREATEBMP(640,480)
SETBMP newdc,bmpdc
SETDC newdc
circle 50,50,50,50 ' test it
_dc(1) was a system pointer to the immediate screen.

So to transfer this hidden page to the screen you would use one command:
    BITBLT newdc,0,0,640,480,_DC(1),0,0,SRCCOPY
Maybe this will give a hint on a way to code your above source smaller.


Casaber(Posted 2015) [#50]
Nice, but I think we should solve the problem as early as possible, I fixed the issue now.

Iīm not sure what GFA uses, I guess it does what Blitz3D did, and thatīs effecient memory pokeing. (Blitzmax & webbrowsers seem to be exactly 10x slower than B3D.
Whatever B3d and probably GFA aswell, was a good solution. Somehow BlitzMax does't max out on the memory & bus as good.
This kind of performance degrade is also what you see with B3D + DRD3 memory vs B3D+ DRD2 memory.

I guess PIXMAP tries to be an optimized version of what you did in B3D (using writepixelfast and keeping integers in an 2d array (not 1d as the internal multiplication and even shifting beats that kind of optimizaitions, what I remember. And should one use PIXMAP I think you need to get behind the scenes a get to know it to get the most of it, the defult behaviour does too much transffering back and forth than it needs. Iīm no expert on that but thatīs my gut feeling looking at it and trying it.

So poking and pretending to be a GPU is pretty much a no go as I see it. Belive me I used to love this. I still do. But when I see the power you get using GPU you can't ignore that anymore. With shaders you sort of get back to poking and get the best of both worlds again, and I will probably start using that soon as aIīve learned it. I thought I'll start with VBO.

Thereīs lot of ways to use the GPU today, OpenGL is the API which I think they model the hardware after (not direct x so much). It let's you use the different aspects and parts if you know itīs maze. VBO is one way to get this "array" or B3D/GFA :ish going on, pixelshader aswell but ya.. not now.

The "mess" of functions is just whatīs needed to set up to get to use the GPU in that old fashion.




dw817(Posted 2015) [#51]
Ah, looks like you got the ergonomics correct now. No need for screen or image rotation. Good job, Casaber !

Well, maybe not now but SOMETIME I am gonna sit down and pick through this code and try to find just what it is that is making a single virtual screen.

I doubt very seriously all the code is needed to decipher that, not for what I am doing anyways.

Let me ask a question though. what is glewInit(). It's not a function that you wrote nor is it recognized by BlitzMAX internal help. It is also required or your program does not work.


Casaber(Posted 2015) [#52]
I'm with you with that though, but I will try to do the same. Iīm pretty convinced thouhg that surprisingly many opengl commands are needed to enter the right mode and to ya juggle things inside the GPU. But at least about 50% I think should be able to be thrown away aw best.

OpenGL & GPU design is suprisingly complex but also kind of clever I. I think one of the hardest bits are to know every constant parameter for every commands. It's a djungle.

I think GLEW is for extensions, OPENGL has a CORE and then it has EXTENSIONS.
EXTENSIONS are kind of "things graphics card companys and driver /API desingers come up and want to try out." if it works out good, it goes into the standard (CORE).

So GLEWINIT allows extensions (versions of opengl has different cores, and the rest is accessed via extensions).

For example this code is old you can tell. Becuase it has EXT everywhere that you actually can remove. Try remove all the EXT and you'll see it still works. I think itīs becuase they have gone into the CORE by now.


Casaber(Posted 2015) [#53]
Iīm thinking B3D/GFA uses PBO or just something like a very tight lowlevel loop.
PBO is asynchrounous transfer from CPU-GPU so my guess is PBO is the best possible software rendering speed.

We could probably get 1000.000 pixels under 12 msec in BlitzMax using a PBO. Same as B3D & GFA. (Memory and bus capped)
But that is pretty lousy for todays resolutions, so I guess we want to go beyond that. The only good use would be to have PBO and then use the GPU for some fake scaled resolution. That doesnīt sound tempting, Itīs too limited.

PBO is what PIXMAP *should've be* (best possible transaction between CPU and GPU)

While VBO and Shader allows raw GPU power. So that leaves us with only VBO and Shader I guess.

The downside of VBO are read/write pixels, but shaders fills that department as long as you are clever.

Multexture, Stencilbuffer, Depthbuffer are functions I might check in if they are still going strong in all new hardware, or if they are emulated nowadays using some lower functionse.g. shaders. I know that the hardware is getting just simpler and simpler, but above the surface they seem still complex.

Okay so this is one of the two definitive best ways to use a GPU today is my personal conclusion.
I like that. Weīre on the right track.


Casaber(Posted 2015) [#54]
Multitexture might have changed into things called Array textures, Texture atlas, and Bindless textures. God this is a mess more than it have to be. Oh well.


Casaber(Posted 2015) [#55]
Should we just await Vulcan? haha I'm beginning to think so.


dw817(Posted 2016) [#56]


Hmm ? What is Vulcan ? A graphic library ? Not the one I'm familiar with, right ?


xlsior(Posted 2016) [#57]
Hmm ? What is Vulcan ? A graphic library ? Not the one I'm familiar with, right ?


A graphics API, aiming to replace OpenGL for cross-platform graphics:
https://en.wikipedia.org/wiki/Vulkan_(API)


dw817(Posted 2016) [#58]
Thank you, Xlsior. Unless it's gonna speed up my little pixel quest, it might be some time before I'm interested in it. I would have to see some example programs and benchmarks done and written with it to see it's use and validity.

Anything that SIMPLIFIES things for others is always of interest to me.


Endive(Posted 2016) [#59]
You could also use a binary space partitioning tree of sorts where the world was modeled with a tilemap. When a tile was damaged, it would be drawn as four subtiles, and recursively down to whatever your pixel size was.

When a subtile had fewer than a certain number of sub-sub-tiles active in it, it would be destroyed.

This would also allow you to do connectivity testing so that when a piece was completely chiseled away from its support, it would fall.


EdzUp MkII(Posted 2016) [#60]
Erm surely dividing the game level into tiles and working out what tiles are damaged by the x,y and radius of the explosion then drawing them and removing explosion area.

This way when the level I'd drawn it's damaged :) Much easier and it's how I did a scorched tanks game that worked on a CGA IBM XT for me brother ;)


dw817(Posted 2016) [#61]
Well now EdzUp, this is initially how I handled pixels back in Floating Point Basic, Turbo Pascal, F-Basic, GwBasic, Q-Basic, and GFA. I would use an array and CHECK before I plot to ensure that it was not already lit and the same color.

You could also do this for tiles or any other elements where you had a large and different number of on the screen. Doing this also ensured smooth graphics with no flickering.

Dissecting the machine-code for Ultima II, I saw they were doing this, whereas in Ultima I, they were not. I knew something was up when the mapper got faster with less details on the screen and slower with. It required some closer investigation. :)

Today however computers are so darned fast that its not really an issue. Still - any library or routine that goes faster than writepixel() I would definitely be interested in as it's a ton of fun to write your own complex graphic libraries that work one pixel at a time and still maintain 30fps.


Endive(Posted 2016) [#62]
That's essentially dirtyrects. Are you sure Garriot did a per-pixel check before drawing? Did he do that or did he check the grid to see if a given shape had already been drawn? Had to have been the latter.

This sort of thing is still an issue on mobiles.


dw817(Posted 2016) [#63]
Sorry to leave you hanging, Casaber. I'm using your miracle code here to demonstrate how powerful it is. Here is a simple map scroller, with a difference. The map is actually a virtual 1024x1024 pixel field.

I was messing all last night with chopping out bits of unnecessary code from the library - when I gave it some thought, what if something doesn't work later ?

So, I opted to keep ALL the code even though I know half of it isn't being used nor will I ever use it. But code space is cheap - just file it away under "crazy code" and everything will turn out alright. :)



Why does this run so fast ? Because NOTHING is being drawn to the screen, that's already been done ahead of time. The only actual code that is running is to clear the screen, plot two images on top of each other - read the arrow keys to adjust X & Y for plotting the first image, repeat, done.

I can't even get my CPU to register 1% usage out of this, that's NICE !