How to grab the backbuffer *with* alpha
BlitzMax Forums/BlitzMax Programming/How to grab the backbuffer *with* alpha
| ||
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? |
| ||
Did you specify the correct Pixmap Format? ;) |
| ||
I'm pretty sure the backbuffer doesn't have alpha :) |
| ||
If the backbuffer had alpha you'd be able to see all the electronics and stuff inside your monitor. |
| ||
LOL |
| ||
*gggg* Nope you wouldn't but you would see your desktop normally (as if you set window alpha) |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
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 |
| ||
The RGBA data is stored all in one place as sequential data. |
| ||
What on earth is "*gggg*"??? >.< |
| ||
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????? |
| ||
Your code works fine on my Radeon 8500 with correct looking alpha saved in the image. |
| ||
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. |
| ||
what does your graphics() fix look like |
| ||
glmax2d.bmx: line 361Method 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. |
| ||
Mabe it's an unsupported feature of your gfx card? |
| ||
maybe, Did it work for you? |
| ||
I'm trying to get this to work inside a canvas. Any tips? There isn't even a Method Graphics() in glmax2d anymore. |
| ||
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. |
| ||
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... |
| ||
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. |
| ||
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: |
| ||
In MaxGUI your desktop has to be 32-bit with destination alpha and then also your graphics context will then be the same. |