Creating a masked sprite
Blitz3D Forums/Blitz3D Beginners Area/Creating a masked sprite
| ||
Hi guys, I've tried everything I can think of (AFAIK) and cannot find the solution. I want to make a sprite and a texture where black is transparant and everything else opaque. ; This routine creates a sprite in the center of the playfield with the given text on it Function CreateCenterSprite(T$) ; Calculate the width and height of the text Local Width = StringWidth(T$) : Local Height = StringHeight(T$) ; Create the sprite and it's texture Local Sprite = CreateSprite() ; Create a texture Local Tex = CreateTexture(128, 64) ; Put the texture onto the sprite EntityTexture Sprite, Tex ; Position and scale the sprite PositionEntity Sprite, 75, 60, -10 ScaleSprite Sprite, 20, 10 ; Set the drawing buffer to the spritetexture SetBuffer TextureBuffer(Tex) ; Make the background black ClsColor 0, 0, 0 : Cls ; Set drawing color to white Color 255, 255, 255 ; Print the text onto the texture (in the center of the texture) Text (128 / 2) - (Width / 2), (64 / 2) - (Height / 2), T$ ; Set the drawing buffer back to the backbuffer SetBuffer BackBuffer() ; Mask the texture (make all black pixels see-through) MaskTexture(Tex) ; Free the texture FreeTexture Tex ; Return the sprite to the calling routine Return Sprite End Function ; This routine will give an alpha of 0 (completely see-through) to any black pixels in the given texture (the rest will remain opaque) Function MaskTexture(Texture) Local NewRGB ; Lock the texturebuffer (required to use ReadPixelFast and WritePixelFast) LockBuffer TextureBuffer(Texture) ; Loop through all pixels in the texture For y = 0 To TextureHeight(texture) - 1 For x = 0 To TextureWidth(texture) - 1 ; Read the RGB value from the texture RGB1 = ReadPixelFast(x, y, TextureBuffer(Texture)) ; Separate the Red, Green and Blue values, also Alpha Red = (RGB1 And $FF0000) Shr 16 Green = (RGB1 And $FF00) Shr 8 Blue = RGB1 And $FF Alpha = (RGB1 And $FF000000) Shr 24 ; If the color is black (Red=0, Green=0, Blue=0) If (Red = 0) And (Green = 0) And (Blue = 0) Then ; Set the pixel completely alpha'd (invisible) Alpha = 0 Else ; Set the pixel opaque (visible) Alpha = 255 EndIf ; Combine the ARGB back into one value NewRGB = (Alpha Shl 24) Or (Red Shl 16) Or (Green Shl 8) Or Blue ; Re-write the pixel with it's new alpha-value WritePixelFast(x, y, NewRGB, TextureBuffer(Texture)) Next Next ; Unlock the texturebuffer UnlockBuffer TextureBuffer(Texture) End Function I did some searching and found the MaskTexture function somewhere in the code-archives, but I've simplified it to suit my needs (I didn't need some extra parameters to include tolerance). In the CreateCenterSprite function, If I use "CreateTexture(128, 64)", then everything remains visible, also the black parts (see picture below). If I use "CreateTexture(128, 64, 2+1)" or "CreateTexture(128, 64, 4+1)", my texture is completely transparent (I don't see anything of my sprite). If I use "CreateTexture(128, 64, 2+1)" or "CreateTexture(128, 64, 4+1)", and the call to MaskTexture is commented, then my sprite appears completely black (the text isn't shown anymore, just a black rectangular sprite). How can I keep my (white) text visible and make the black background completely transparent? The CreateCenterSprite is used to create the sprite in the middle of the playfield that shows: "Level: 1". As you can see, it's shown completely. I want the black parts to be transparent. |
| ||
The combination of creating the texture using the 1+2 flags and MaskTexture should work. I remember that when using sprites, I encountered the same problem. I worked around that by loading an empty sprite using LoadImage with the 1+2 flags. When I wanted to test this out, I noticed my machine doesn't create sprites at all. When I use LoadSprite, I get a MAV on Renderworld. So I had to test it with a cube instead of a sprite. That seems to work as expected, maybe you can give it a try as well. If so, you could perhaps decide to use a Quad mesh instead of a sprite. |
| ||
I tried creating my own sprite, using the CreateMesh/CreateSurface/AddVertex/AddTriangle method, but the result was the same. Your example wrote the text to the BackBuffer() and you copyrected the part you needed onto the texture. This gave me an idea. I now tried to create an image first, draw my text onto the image and copyrect the image to the texture. And finally using the MaskTexture function. This worked flawlessly. I guess Blitz has problems doing any drawing onto a texture directly. Especially Text as I've experienced other problems in that area. Thanks for helping out Warner. ; This routine creates a sprite in the center of the playfield with the given text on it Function CreateCenterSprite(T$) ; Calculate the width and height of the text Local Width = StringWidth(T$) : Local Height = StringHeight(T$) ; Create the sprite and it's texture Local Sprite = CreateSprite() Local Tex = CreateTexture(128, 64, 2+1) Local Image = CreateImage(128, 64) ; Position and scale the sprite PositionEntity Sprite, 75, 60, -10 ScaleSprite Sprite, 20, 10 ; Set the drawing buffer to the image SetBuffer ImageBuffer(Image) ; Make the background black ClsColor 0, 0, 0 : Cls ; Set drawing color to white Color 255, 255, 255 ; Print the text onto the image (in the center of the image) Text (128 / 2) - (Width / 2), (64 / 2) - (Height / 2), T$ ; Set the drawing buffer back to the backbuffer SetBuffer BackBuffer() ; CopyRect the entire image to the texture CopyRect 0, 0, 128, 64, 0, 0, ImageBuffer(Image), TextureBuffer(Tex) ; Mask the texture (make all black pixels see-through) MaskTexture(Tex) ; Put the texture onto the sprite and free the texture and the image EntityTexture Sprite, Tex FreeTexture Tex FreeImage Image ; Return the sprite to the calling routine Return Sprite End Function |
| ||
I have a routine in my archive entries. You simply pass across a texture to it and a colour and it masks off any pixels/texels of that colour: http://www.blitzbasic.com/codearcs/codearcs.php?code=1013 |
| ||
Yes Ross, I searched the code archives and found your code. The MaskTexture() function in my first post was originally your code, slightly adjusted to exclude tolerance. |
| ||
Ah sorry :S It was late :D Glad you got it sorted! |
| ||
I sorted it out after a few hours of breaking my head over this problem. The only solution was to create an image, write all text/lines/rects/... to this image and then copyrect that image onto the texture. And finally using the MaskTexture function to make parts of the texture which use a certain color see-through (alpha'd). Writing directly onto the texture doesn't work properly. |