Is there a 2D "EntityAlpha"-like command?

Blitz3D Forums/Blitz3D Beginners Area/Is there a 2D "EntityAlpha"-like command?

Caleb(Posted 2010) [#1]
So I was wondering if there was something in here that allows you to change the transparency of an image. I've searched several times, but I think I might be overlooking it. My current method is to change images to sprites and use EntityAlpha to make them transparent, but this is tedious and doesn't always work if I'm checking for collisions.

Plz help!


Matty(Posted 2010) [#2]
Do you mean using the 2d commandset - in which case you need to manually blend each pixel using writepixelfast/readpixelfast?

If you mean using the 3d command set, with sprites, then you can do so in your image editing program by setting the alpha value of each pixel in the image there and loading it as a texture using flags 1+2.


Caleb(Posted 2010) [#3]
In the 2D commandset.

I'm not really good with buffers and all that reading/writing pixels stuff.. so can you explain kinda what I have to do?


Matty(Posted 2010) [#4]
Okay. To alpha blend an image with another image (which is effectively what you are doing with an alpha command)
(Also - it will be slow as pixel by pixel image manipulation commands are not exactly quick).


Graphics 800,600,0,2

image1 = LoadImage("myfirstimage.bmp")
image2 = LoadImage("mysecondimage.bmp")
;assumes they are the same dimensions - and fits on the screen

alphalevel#=0.5
;blend the images together and draw them to the backbuffer..

SetBuffer BackBuffer()
LockBuffer BackBuffer()
LockBuffer ImageBuffer(image1)
LockBuffer ImageBuffer(image2)
For x=0 To ImageWidth(image1)-1
	For y=0 To ImageHeight(image1)-1
		col1=ReadPixelFast(x,y,ImageBuffer(image1))
		col2=ReadPixelFast(x,y,ImageBuffer(image2))
		r1=(col1 Shr 16) And 255	;get's the red component of pixel on image 1
		g1=(col1 Shr 8) And 255 ;green component
		b1=(col1 And 255) 

		r2=(col2 Shr 16) And 255	;get's the red component of pixel on image 2
		g2=(col2 Shr 8) And 255 ;green component
		b2=(col2 And 255) 



		;mix the components according to the alphalevel..if alpha = 1 then color will be all image 2, if alpha=0 color will be all image 1
		r1=Float(r1) + Float(r2 - r1)*alphalevel
		g1=Float(g1) + Float(g2 - g1)*alphalevel
		b1=Float(b1) + Float(b2 - b1)*alphalevel

		If x<800 And y<600 Then WritePixelFast x,y,(r1 Shl 16)	Or (g1 Shl 8) Or (b1)

	Next
Next
UnlockBuffer ImageBuffer(image2)
UnlockBuffer ImageBuffer(image1)
UnlockBuffer BackBuffer()

Flip
WaitKey
FreeImage image1
FreeImage image2
End




Caleb(Posted 2010) [#5]
Seems complex for such a little element, but it works. Thanks alot.


Fernhout(Posted 2010) [#6]
I tested this and its uselfull, but i see one little problem to solve here. e.g. my background is also a image and put that first then do the alpha. the whole second images wil blend in with the background screen. Its nice but the transpance color (Black) is also draw as a part of the picture That has to be left out in the calculation.

But again thanks for the idea now i can do something i wanted to to the whole time to make a logo with shadow.If its works i put you name in the info to as a good help for the program.


Ross C(Posted 2010) [#7]
If your background is static, you could cache the background pixel values in an array and read from that, instead of reading from the buffer. Same with the image.


Fernhout(Posted 2010) [#8]
I try that to do it in an array, but it slow down the program. I have found a way to do it. I did make a function of it and it works great.
The program i am making is in its completion stage. Its now time to clean up the code and make some test runs. Using my wife as a tester.


K(Posted 2010) [#9]
Cool Matty,
I could really use this on a project of mine.But I would need more speed.
Do you think writing this as a DLL for the userlibs would make it run better?


Yasha(Posted 2010) [#10]
Just use this: http://www.blitzbasic.com/Community/posts.php?topic=92270

Fastest possible solution.


K(Posted 2010) [#11]
Yasha,
I have the .Rar in the userlibs,is that right?not sure how to open it...


Yasha(Posted 2010) [#12]
Not quite.

First thing - .rar is a proprietary archive format (i.e. a bit like .zip only not); you'll need to unpack the files from it using either WinRAR (unlimited free trial but you're supposed to pay for it) or a free alternative like 7-Zip. Unpack the contents of the archive anywhere (doesn't have to be in userlibs).

Once you've done that, the only thing you need to copy to your userlibs folder is Draw3D2.decls, the other two .decls files are optional (they only pretty-print the commands, no DLLs involved).

The only thing you need to do to use the library is include Draw3D2.bb (or either of the others if you want to use those) into your project. The includes arefound in the "Includes" subfolder. The subfolders marked with underscores provide examples of using the commands.


K(Posted 2010) [#13]
Thank you.Seems a bit strange for a German to use Russian encryption, why did Hectic use .RAR?Just curious.


UM...there are many of them.Cool. Thanks Yasha.

Last edited 2010


fox95871(Posted 2010) [#14]
I use a mesh anchored to the camera for EntityAlpha and other such effects. It takes a little work to get it lined up just right, but it's worth it. To do it, make a 640 x 480 image, or whatever your preferred screen resolution is, and make it black, with white four pixel dots near each corner. Then, make a 4:3 CreateMesh plane with controls for moving the vertexes, and an autosave file for their positions. When you get it roughly lined up with the camera, start moving the vertexes very slowly until it lines up with the actual 2D image. From there, you can get pretty specific by taking screenshots and checking the colors in Photoshop until the four pixel dots of the 3D overlay are all 255,255,255. I found it to be impossible to get it exactly right, and eventually just accepted it having a slight margin of error, but you might be able to get all the pixels pure white. One last thing, whatever your final 2D images are supposed to be, always convert them to a square power of two before saving them, or you'll end up with artifacts when it gets put on the mesh. Sorry for the long post, but it's a complicated process. In the end though, you'll have 2D graphics with all the great effects of textures.

Last edited 2010


Robert Cummings(Posted 2010) [#15]
why are you doing it in 2D, why not use 3D to emulate 2D? Is it an art package you are making?


jfk EO-11110(Posted 2010) [#16]
did anybody mention this:
http://www.blitzbasic.com/toolbox/toolbox.php?tool=71


Mahan(Posted 2010) [#17]
@jfk EO-11110:

nSprite II does not work very good under Windows 7. Last time i fired up an old project I had that uses it, the GUI module (part of nSprite II) was not working at all, and there where several issues in the normal demos with the graphics as well.

I haven't tried it with 1.106, but since it uses quads internally (and no B3D sprite functions) I suspect it still has the same problems.

(n.b: I haven't contacted the author about these issues so far.)


jfk EO-11110(Posted 2010) [#18]
I didn'n know that, but since there are many problems with sprites on not-so-old machines, and some of them have been fixed with the replacement of sprites by quads (eg. in my fps project) I am rather surprised. Maybe it's the other way round, i mean, "nSprites"- it even has Sprites in the name.


K(Posted 2010) [#19]
Forgive me for hijacking,and I apologize for repeatedly posting dumb ideas
like this, but the reason this interests me is i had in mind a
built-from-scratch 3d engine that doesn't use the 3d command set,and thus doesn't upload anything to the 3d graphics drivers in the video card

My idea was to use actual video stitched into panoramas that i would blend together and that's where the probem lies:

At any given point I need to draw 2+ panos to backbuffer() and I need to blend them together using alpha.

I like this Draw3d2, but it uses quads to emulate image alpha and the defeats the whole purpose. None of my alpha routines are fast enough and I can't find anything in the arcs that can handle images above 180X180 at reasonable speed.

Does this idea even make sense?

Last edited 2010


Adam Novagen(Posted 2010) [#20]
The idea makes sense, but I have to tell you that in execution it won't work in Blitz3D.

First item: a software-based 3D engine (where the PROGRAM calculates and renders 3D graphics using 2D drawing commands) is, to my knowledge, always MUCH SLOWER than a HARDWARE-based engine. This is because software rendering completely ignores the 3D hardware in the video card and uses the CPU instead. GPUs (Graphics Processor Units) are built and designed to make 3D graphics happen. CPUs are not.

Second item: Blitz Basic, BlitzPlus and Blitz3D are by far some of the worst languages you could choose for pixel-by-pixel coding. This is because all three of them use DX7 (maybe even less in Blitz/BlitzPlus). By DX8, pixel manipulation for things like realtime scaling, rotation and alpha blending became fast, frequent and common, because the 2D drawing commands were done by the 3D hardware. DX7 and earlier has no such ability; 3D is 3D and 2D is 2D.

In short, your alpha routines never WILL be fast enough because it simply isn't graphically possible, in Blitz 3D or ANY DX7-based (or lower) application that I know of. My best advice to you would be to invest in Blitz MAX. BMax uses, I believe, some version of OpenGL, which gives you access to that 3D-2D goodness. It WILL STILL USE 3D HARDWARE TO RENDER 2D IMAGERY. However, although you didn't know it, this is how almost ALL 2D games and programs work nowadays, for the reasons I stated above. If you want to be in with the times, you'll just have to move with 'em; to be quite frank, even I, a diehard Blitz3D junkie, will probably be porting to another language - at the very least BMax - after I've finished my current game project.


jfk EO-11110(Posted 2010) [#21]
What you could do for a simple 50:50 alphablending is this: take pixel 1 and pixel 2, both in the rgb range of $FFFFFF.

Then shift them one bit to the right, making them half bright:
rgb1=(rgb1 and $fefefe) shr 1
rgb2=(rgb2 and $fefefe) shr1

then mix them:

rgb3=rgb1+rgb2

then write the pixel back. But I have to say, since you have to access the DirectDraw imagebuffers with Readpixelfast, this is reeeaally slow.

An alternative would be a checkerboard masked mix of two images. It looks ok when the bightness of the two images is similar.
Graphics 800,600,32,2
SetBuffer BackBuffer()

w=256
h=256

Dim f1(w,h)
Dim f2(w,h)

Global img_raster=createRaster(w,h)
Global img_mixer=CreateImage(w,h)

img1=LoadImage("wall.jpg")
Print img1
img2=LoadImage("floor.jpg")
Print img2

img3 = CreateMixedImage(img1,img2)

; or simply update a mix:

; speed test:
ms=MilliSecs()
For i=0 To 100
 MixImagesCheckerboard(img1,img2,img3,ImageWidth(img1),ImageHeight(img1))
Next
ms2=MilliSecs()


Cls
DrawBlock img3, 0,0
DrawBlock img1, w,0
DrawBlock img2, w+w,0
Print ms2-ms


Flip
WaitKey()
End



Function CreateMixedImage(img1,img2)
 w=ImageWidth(img1)
 h=ImageHeight(img1)
 w2=ImageWidth(img2)
 h2=ImageHeight(img2)
 If (w<>w2) Or (h<>h2)  ;should be used with similar sizes, however scaling if required
  ResizeImage img2,w,h
 EndIf
 img3=CreateImage(w,h)
 MixImagesCheckerboard(img1,img2,img3,w,h)
 Return img3
End Function








Function MixImagesCheckerboard(img1,img2,img3,w,h)
 DrawBlock img1,0,0
 DrawImage img_raster,0,0
 CopyRect 0,0,w,h,0,0,BackBuffer(),ImageBuffer(img_mixer)
 DrawBlock img2,0,0
 DrawImage img_mixer,0,0
 CopyRect 0,0,w,h,0,0,BackBuffer(),ImageBuffer(img3)
End Function


Function CreateRaster(w=1024,h=1024)
 Color 64,64,64
 im=CreateImage(w,h)
 SetBuffer ImageBuffer(im)
 For y=0 To w-1
  For x=0 To h-1
   If (((x And 1) =1) And ((y And 1)=0)) Or (((x And 1)=0) And ((y And 1)=1))
    Plot x,y
   EndIf
  Next
 Next
 SetBuffer BackBuffer()
 MaskImage im,64,64,64
 Return im
end function


Last edited 2010


K(Posted 2010) [#22]
@JFK: I would do that but I was going to use actual videos,not stills.
EDIT:Oh, okay,took me a second there.Yeah I would do that but I need dynamic alpha adjust since the char would be in motion, so 50:50 doesn't cut it. I tried the checker idea already with bands that were 10*1 pixels,but it didn't work quite well.
___
@Novagen: I see your point.The only thing I have to say is I wasn't using any 3d 3d,by which I mean, I wasn't going to use any tris,etc. But I see what your'e saying.Would there be some way I could punch it to the GPU.

EDIT: Or, this is a dumb question maybe, but is there a DLL floating around somewhere that would return an entire buffer as a data stream/bank
in one request, instead of requesting each pixels?
I guess if not then not.I've toileted projects before, and this might just be another one.

Last edited 2010

Last edited 2010


Yasha(Posted 2010) [#23]
Yeah, you can use the Windows function RtlMoveMemory to copy a whole block of data at once... it's ludicrously fast. Lock the buffer, RtlMoveMemory the contents of a bank over it, unlock the buffer. It's a Kernel32 function so you don't need any distributable DLLs. There are several examples of this floating around the forums (you might also need a function to let you access memory addresses.. I forget the exact details).

The problem is that the only thing that's much faster is the step of actually getting the data into the buffer. It still takes some time to unlock the image/texture (i.e. re-upload the buffer data to the GPU), and more importantly, iterating a loop over every "pixel" in a bank is still actually pretty slow (bank operations are fast on an individual level... a million of them per frame does add up to a noticeable figure).


K(Posted 2010) [#24]
@Yasha: would it be possible to do this in reverse. Like,

Buffer>>Rtlmovememory>>Bank>>Modify>>Rtlmovememory>>Buffer?

Still be too slow I guess.I only need this for one image in the whole game,
the background pano. I'm thinking Adam's right, and it's just not feasable.
But it can't hurt to try a bit.


Yasha(Posted 2010) [#25]
@Yasha: would it be possible to do this in reverse. Like,

Buffer>>Rtlmovememory>>Bank>>Modify>>Rtlmovememory>>Buffer?


No reason why not (RtlMoveMemory is just a copy command that works on arbitrary data at a given address)... but you could avoid some hassle by simply creating the image in place in the bank (if it's in a file, initialising it once with WritePixelFast before your main loop won't be noticeable) and doing all your operations on it there. Unless you're updating the buffer by some other means too (e.g. Text, drawing), the data in the bank will still be accurate.


K(Posted 2010) [#26]
Thanks all three of you.Sorry about the hassle.
Working on two avenues for it now.Guess which is more successful? 3d. Your right Adam, just roll with the times.

Dadburn young people,with there :)s, and fancy-pants abacus screens!


K(Posted 2011) [#27]
Sorry to resurrect this,but I have a question. RtlMoveMemory, can I dump data DIRECTLY into BackBuffer with it? I'm afraid to fry my GPU/computer so thought I'd ask first.

Or perhaps more importantly, would said dumped data display properly, if it can be done that is.

Last edited 2011


Kryzon(Posted 2011) [#28]
You can dump data directly, but I believe the backbuffer is a DirectDraw Surface, so any memory you write directly to it will need to undergo some messaging from Windows\DirectX to update and will be really slow.
This is actually the reason why plotting pixels is slow (not only in Blitz products but with any engine).

Pixel-perfect 2D in 3D is the way to go. Every major engine is using this; you not only get rendering benefits (blending and filtering) but transformation also (rotation and scale). Making sure the engine you are using is pixel-perfect guarantees you the same visuals as you would have, say, if you used the old 2D-only DirectDraw API.
If you want to be aware of the capabilities of a commercial grade 2D in 3D engine, check the FastImage library demo for Blitz3D.


Yasha(Posted 2011) [#29]
For the purposes of playing about with pixels writing directly to the backbuffer should be pretty much the same as anything else. It's certainly not dangerous (EDIT: as long as you don't overflow or any of the other things you can normally break using direct pointers!).

You'll have some fun and games working out the correct offsets and so on though. THIS old classic may be of some use (Mikhail really is The Man).

Last edited 2011


K(Posted 2011) [#30]
Yeah Kryzon, I agree, but I'm short of Cash right now. Just trying to lay abit of groundwork until I can port to Max/monkey- the awful debate.
@Yasha: very interesting... thanks.You're right, he's a real smart feller.


Kryzon(Posted 2011) [#31]
Yeah Kryzon, I agree, but I'm short of Cash right now.

Draw3D
Sprite Control