Translucency in 2D
BlitzPlus Forums/BlitzPlus Programming/Translucency in 2D
| ||
Hi all, just bought B3D and this is my first post! I've been working on a retro style rpg game, like a modernised version of the old Moria games :). The reason I write using 2D is because I can't get my head around 3D modelling (at least not complicated models like humans), but I want to be able to do cool effects like alpha channels with 2D blits. I understand fully that DirectDraw doesn't support this feature natively. I also understand that you can cheat and use Direct 3D somehow... maybe using sprites perhaps? Basically if I want to draw a 32x32 image at x, y on the screen with say 80% opacity is it possible? I don't want to maintain the sprite, just dump a copy of it on screen like with DrawImage. I had a play with a trial version of *cough* DarkBasic and this manages to do hardware accelerated 2D style sprites with translucency, but I don't even need anything this complicated - as I said I just want to draw it on the screen and forget about it without having a sprite object present. I thought about using a complex pixel based algorithm to do it, but I am thinking it would be way too slow. So... is it possible in B3D? |
| ||
As far as i know you have you would have to use a sprite, or maybe a textured quad to do this with hardware. There was a function going around a long time ago that could do this in blitz2d, can't find it in the code archives so here is the one on my harddisk (it does hit the CPU hard though): Function draw_alpha(image%, x%, y%, alpha#) ; if the opacity is 100% then no point in rendering the opaque image ; just draw original image If alpha# >= 1 Then han_x% = ImageXHandle(image%) han_y% = ImageYHandle(image%) HandleImage image%, 0, 0 DrawImage image%, x%, y% HandleImage image%, han_x%, han_y% ; else if the opacity is greater than zero (if less the 0 don't bother drawing it!) Else If alpha# > 0 Then nalpha# = 1 - alpha# ; Lock the buffers LockBuffer BackBuffer() LockBuffer ImageBuffer(image%) ; Loop through each pixel in the image, ; To create New opaque image pixel by pixel For xx% = 0 To ImageWidth(image%) For yy% = 0 To ImageHeight(image%) ; Get colors from sprite pixel rgb1% = ReadPixelFast(xx%, yy%, ImageBuffer(image%)) If rgb1% <> 0 Then r1% = ((rgb1 And 16711680) Shr 16) g1% = ((rgb1 And 65280) Shr 8) b1% = (rgb1 And 255) rgb2% = ReadPixelFast(xx + x, yy + y, BackBuffer()) r2% = ((rgb2 And 16711680) Shr 16) g2% = ((rgb2 And 65280) Shr 8) b2% = (rgb2 And 255) ; Calculate the color of the new opaque pixel and draw pixel to new image r3 = r1%*alpha# + r2%*nalpha# g3 = g1%*alpha# + g2%*nalpha# b3 = b1%*alpha# + b2%*nalpha# WritePixelFast(xx + x, yy + y, ((r3 Shl 16) + (g3 Shl 8) + b3), BackBuffer()) End If Next Next ; Unlock the buffers UnlockBuffer BackBuffer() UnlockBuffer ImageBuffer(image%) End If End Function |
| ||
Hey! Are you meaning you just want transparency once? You don't want to update it all the time? |
| ||
Thanks guys. To clarify I'm working on a 2d tile based map engine and I want the alpha for lighting effects. That's why I don't want to use sprites because I don't want to have a sprite for every square on my map. The map is being redrawn constantly. Because I have to do this a lot I can't use the pixel method above... it would be too slow, need some way to tap into the hardware acceleration on the card (2d or 3d). I can't believe theres no way to draw a normal 2d image on the screen with alpha, colouring etc. I had a look at the sprite conrol library someone has written, and although it's very good it does use sprites and textures (therefore having a sprite list to maintain and not getting a pixel accurate copy of the image). Any more suggestions? |
| ||
well, do the shadows ever project onto moving images or tiles? I'd imagine they do. mmmm. You could use the checked shadow approach.#.#.#.#.#. .#.#.#.#.# #.#.#.#.#. .#.#.#.#.# #.#.#.#.#. .#.#.#.#.# basically meaning that #=a pixel of the image and .=a black pixel. It tricks the eye into thinking the image is transparent. Use only on resolutions 800x600 or greater. And also, don't let any of these checked shadows overlap, cause it looks kinda bad. Hope that helps! [EDIT] sorry, sounds a bit vague. For the shadows your wanting, make the shadow a very dark grey, but NOT black. Then checker the image with black pixel. I sent you an image to show you what i mean, only it's a circle. |
| ||
This code uses jokers approach but allows images to overlap and keep their transparency, but its very inefficient. (needs images argb values stored in the pic(width,height) array) LockBuffer For x=xx To picw+xx If x=>0 And x<gw If x Mod 2 > 0 Then For y=yy To pich+yy If y=>0 And x<gh And pic(x-xx,y-yy)>-16777216 If y Mod 2=0 Then WritePixelFast x,y,pic(x-xx,y-yy) EndIf Next Else For y=yy To pich+yy If y=>0 And x<gh And pic(x-xx,y-yy)>-16777216 If y Mod 2>0 Then WritePixelFast x,y,pic(x-xx,y-yy) EndIf Next EndIf EndIf Next UnlockBuffer |