How to grab the backbuffer *with* alpha

BlitzMax Forums/BlitzMax Programming/How to grab the backbuffer *with* alpha

GW(Posted 2005) [#1]
Can this be done im Blitzmax? Blitz3D could do it, but i cant get it to work in Bmax. Looking at the code for the grabpixmap command it seems to to be using RGBA, but the pixmap thats returned is always RGB. Any ideas?


Dreamora(Posted 2005) [#2]
Did you specify the correct Pixmap Format? ;)


fredborg(Posted 2005) [#3]
I'm pretty sure the backbuffer doesn't have alpha :)


John Pickford(Posted 2005) [#4]
If the backbuffer had alpha you'd be able to see all the electronics and stuff inside your monitor.


Dirk Krause(Posted 2005) [#5]
LOL


Dreamora(Posted 2005) [#6]
*gggg*

Nope you wouldn't but you would see your desktop normally (as if you set window alpha)


ImaginaryHuman(Posted 2005) [#7]
The backbuffer does have alpha. I'm not sure if it has alpha using Graphics but it does if you specify BGL_ALPHABUFFER as one of the flags for bglCreateContext. It's perfectly possible to grab any of the buffer content RGBA or even just A, into a pixmap. Just make sure the pixmap you grab into is, itself, already set up to have that format. If you loaded a plain RGB image it wont have an alpha channel or space to store alpha. You should look at ConvertPixmap() to make sure it become PF_RGBA8888 before you do the grab.


GW(Posted 2005) [#8]
Thanks Angeldaniel, The pixmap returned from GrabPixmap is already specified as RGBA and the glReadpixels command it uses is also using RGBA, however the pixmap returned is always with alpha of $FF. So it seems that the backbuffer is the culprit of being RGB and not RGBA.
If I were to make my own call to bglCreateContext for getting this to work, what other steps do I need to do to get a valid window thats ready for max2d commands?
Would it be easier to just modify the BglCreatecontext command and recompile the modules, than to do my own window setup? I dont know GL that well yet and i dont want break what little compatability Max2d has already.


ImaginaryHuman(Posted 2005) [#9]
Um ... you do need several other OpenGL calls to properly set up a context with bglCreateContext. It would be easier to modify the module code for Graphics instead, to include BGL_ALPHABUFFER as a flag.

As a side note, a bglCreateContext always creates a Depth buffer whether you want one or not, I don't know why.


GW(Posted 2005) [#10]
I've modified the graphics command to include BGL_ALPHABUFFER but still no luck. ;(

what am i missing?
Is the Alpha buffer a different buffer than the backbuffer, Maybe im looking in the wrong place to read it?


skidracer(Posted 2005) [#11]
You will also need a modified CLS color, this code seems to be working (after hacking BGL_ALPHABUFFER flag into Graphics()), although not absolutely sure of that:

Function SetClsColor2( red,green,blue,alpha=255 )
	glClearColor red/255.0,green/255.0,blue/255.0,alpha/255.0
End Function

Graphics 640,480,32

SetClsColor2 255,0,0,0

Cls

DrawLine 0,0,32,32
DrawLine 32,0,0,32
DrawOval 0,0,32,32

Local image=CreateImage(32,32,1,DYNAMIC_IMAGE)
GrabImage image,0,0

Cls
For Local i=1 To 100
	DrawImage image,rnd(640),rnd(480)
Next
Flip

WaitKey



ImaginaryHuman(Posted 2005) [#12]
The RGBA data is stored all in one place as sequential data.


Damien Sturdy(Posted 2005) [#13]
What on earth is "*gggg*"??? >.<


GW(Posted 2005) [#14]
Thanks skidracer, but that doesn't seem to work.
In all my tests the alpha byte is always $FF.
Changing the last argument of SetClsColor2 seems to have no effect on the backbuffer.
Here is a small example:

Const Image$ = "good1.tga"

Graphics 800,600,32,0

Function SetClsColor2( red,green,blue,alpha=255 )
	glClearColor red/255.0,green/255.0,blue/255.0,alpha/255.0
End Function

Global TestImage:tImage = LoadImage(Image$)

SetClsColor2(0,0,0,0)
SetBlend(ALPHABLEND)

While Not KeyHit(KEY_ESCAPE)
	Cls
	SetAlpha(0.8)
	SetScale 0.5,0.5
	DrawImage(Testimage,MouseX(),MouseY())
	
	If KeyHit(KEY_BACKSPACE) Then
		saveTGA("Testsave.tga",GrabPixmap(0,0,800,600),800,600)
	End If

	Flip
Wend
Function SaveTGA(Name$,PM:tPixmap,W,H)
	Local f,width%,height%,x%,y%
	Local pix,IR,IG,IB,alpha
	f=WriteFile(name$)
	WriteByte(f,0) 'idlength
	WriteByte(f,0) 'colormaptype
	WriteByte(f,2) 'imagetype 2=rgb
	WriteShort(f,0) 'colormapindex
	WriteShort(f,0) 'colormapnumentries
	WriteByte(f,0) 'colormapsize 
	WriteShort(f,0) 'xorigin
	WriteShort(f,0) 'yorigin
	WriteShort(f,w) 'width
	WriteShort(f,h) 'height
	WriteByte(f,32) 'pixsize
	WriteByte(f,8) 'attributes
	For y=H-1 To 0 Step -1
        	For x=0 To w-1
			pix = ReadPixel(PM,X,Y)
			WriteInt(f,pix)
		Next
	Next
	CloseFile(f)
End Function 


loading the saved image in photoshop or a hex editor shows that no alpha was preserved from the back buffer.
Is there any way at all to get alpha from the back buffer?????


skidracer(Posted 2005) [#15]
Your code works fine on my Radeon 8500 with correct looking alpha saved in the image.


GW(Posted 2005) [#16]
hmmm really?
So in the exported image, everywhere that that was blank was $00000000 and not $000000FF? For me, the image is exported looking correctly, but the alpha channel is full white.
thanks for testing it btw.


skidracer(Posted 2005) [#17]
what does your graphics() fix look like


GW(Posted 2005) [#18]
glmax2d.bmx: line 361
Method Graphics( width,height,depth,hertz )
		Local bgl_flags=BGL_BACKBUFFER|BGL_ALPHABUFFER
		'Local bgl_flags=BGL_BACKBUFFER
....


I'm willing to concede that it could be my graphics card [geforce2 GTS/32m] or something else. If someone can confirm that my sample code above does truly render a tga with the empty space having alpha $00 and preserving the alpha of loaded image, then that would be good enough for me.


ImaginaryHuman(Posted 2005) [#19]
Mabe it's an unsupported feature of your gfx card?


GW(Posted 2005) [#20]
maybe, Did it work for you?


Raph(Posted 2008) [#21]
I'm trying to get this to work inside a canvas. Any tips? There isn't even a Method Graphics() in glmax2d anymore.


klepto2(Posted 2008) [#22]
If you have a moderate Gfx card try this instead:
http://www.blitzbasic.com/codearcs/codearcs.php?code=2222

It uses FBOs for direct r2t and it is much faster than the readpixel stuff.


EPS(Posted 2008) [#23]
Here my method:

Render the Backbuffer twice. First on $FFFFFF (white) as Background Color and then on $000000 (black) as Background Color. Grab both rendered images and with that you can calculate the Alpha Transparency into a third Image/Buffer.

Not really fast - but possible.

sorry for my bad english...


ImaginaryHuman(Posted 2008) [#24]
It should be possible to grab it without any fancy extras. You have to make sure you ask for a 32-bit backbuffer and must ask also for an alpha buffer. Then you get a destination alpha, so long as your graphics card does 32-bit mode not 24-bit. Then a simple glReadPixels() will read the contents, or you can grab the backbuffer into a texture. I know it works because I switch off the RGB channels and grab only the destination alpa channel into a GL_ALPHA texture and use that texture to do rendering, which I know works.


Raph(Posted 2008) [#25]
As it happens, I have need to do other sorts of pixel processing & don't need this in realtime, so East-Power-Soft's method works well for me. :) Thanks for the tips, though -- that's a nice r2t routine, hadn't seen it before, klepto.

ImaginaryHuman, I have no idea how to accomplish that in MaxGUI, that's why I was asking. :)

Here's what I ended up doing:




ImaginaryHuman(Posted 2008) [#26]
In MaxGUI your desktop has to be 32-bit with destination alpha and then also your graphics context will then be the same.