Text above players' head: transparancy

Blitz3D Forums/Blitz3D Programming/Text above players' head: transparancy

	DeleteChatBalloonFromPlayer(whichPlayerIDSaidIt)

	b.chatBalloon = New chatBalloon
	b\timeToLive = timeToLive
	b\entity = LoadSprite("images/chatBalloon.tga",2,theParent)
	b\textEntity = CreateSprite(b\entity)
	b\net_id = whichPlayerIDSaidIt
	

	
	img = CreateImage(128,64)
	SetBuffer ImageBuffer (img)
	ClsColor 255,255,255
	Cls
	Color 0,0,0
	drawText(x2d,y2d,128,64,theText$,4,0)	
	MaskImage img,0,0,0
	b\texture = CreateTexture(128,64,4)
	SetBuffer TextureBuffer(b\texture)
	DrawImage img,0,0
	SetBuffer BackBuffer()
	EntityTexture b\textEntity,b\texture
	Color 255,255,255
	
	; tekst op ballon
	MoveEntity b\textEntity,1.3,1.1,2
	HandleSprite b\textentity,-1,-1
	ScaleSprite b\textEntity,6,2.5
	SpriteViewMode b\textEntity,1
	; ballon
	MoveEntity b\entity,0,1,0
	HandleSprite b\entity,-1,-1
	ScaleSprite b\entity,8,4
	SpriteViewMode b\entity,1



What the above does: create a balloon texture, and place text on a second texture.(it is written to a texture).

The problem: I want the background of the second texture (text) to be transparant. Only the text needs to be shown.
As you can see, I tried masking, but I still get an opaque background.

Anyone?

Thanks!

The problem with creating your textures on the fly is that the alpha channel is apparently set to 255. I had the same problem and the following worked for me. Just stick it in your code after you've created the masked texture.

For x = 0 To TextureHeight
For y = 0 To TextureWidth
WritePixel x,y,0
Next
Next

You have some Bugs in there, better use:

setbuffer texturebuffer(tex)
lockbuffer
For y = 0 To TextureHeight(tex)-1
For x = 0 To TextureWidth(tex)-1
WritePixelfast x,y,0
Next
Next
unlockbuffer

where "tex" is your Texturehandle.

okay, I don't have Blitz on this computer, but these sound like good suggestions; thanks jfk and Stevie G.
I'll look up what Lockbuffer does, the WritePixelFast seems logical now I look at it, I didn't know 'bout the 255 color thing :-D

	; make a new texture, and make it all WHITE
	b\texture = CreateTexture(128,64,4)
	SetBuffer TextureBuffer(b\texture) 
	LockBuffer 
	For y = 0 To TextureHeight(b\texture)-1 
		For x = 0 To TextureWidth(b\texture)-1 
		WritePixelFast x,y,$FFFFFFFF 
		; above, completely white?
		Next 
	Next 
	UnlockBuffer
	
	; draw the image, and place black text on it
	img = CreateImage(128,64)
	SetBuffer ImageBuffer (img)
	Color 0,0,0
	drawText(x2d,y2d,128,64,theText$,4,0)	
	MaskImage img,255,255,255 
	
	; draw the image, go back to normal buffer, set textcolor to 255
	DrawImage img,0,0
	SetBuffer BackBuffer()
	EntityTexture b\textEntity,b\texture
	Color 255,255,255


I still have troubles, I can't see anything except the balloon ansich. I added comments in the code, because somewhere I'm making mistakes (masking?)

Got the same prob myself. Gotta rush out but reckon you have to do something like create texture, then redraw it using;

readpixelfast
writepixelfast(readpixelvalue and $FFFFFF)

to cut off the alpha values

Wouldn't it be easier to have a base texture already created which you then just make a copy of and add the text on top?

*EDIT*
Either that or if it must be created dynamically, couldn't you use the Rect command to fill it in black?

Wouldn't it be easier to have a base texture already created which you then just make a copy of and add the text on top?


Yup, I do that. I load a totally transparent .tga texture and then start drawing on it.

Perturbatio- YES to your first point. I think the problem with just using drawing commands to blank the thing is that they just mod the rgb values not the alpha values that sit on them (I may be wrong on this). The blitz docs recommend creating your textures in a standard image bank <createimage> then copying this to a texture bank with copyrect- apparently it may be the fastest option. Not sure what alpha values u end up with doing this.

Function do_mask(texture,maskr=0,maskg=0,maskb=0)
	maskcol=(maskr Shl 16)+(maskg Shl 8)+maskb
	LockBuffer TextureBuffer(texture)
	For x=0 To TextureWidth(texture)-1
		For y=0 To TextureWidth(texture)-1
			pix=ReadPixelFast(x,y)
			If (pix And $FFFFFF)=maskcol WritePixelFast x,y,(pix Or $FF000000) Else WritePixelFast x,y,0
		Next
	Next
	UnlockBuffer TextureBuffer(texture)
End Function


Another alternative -
create texture, draw to it, then send it to the above function specifying the (r,g,b) value you want to be c-thru
(defaults to black 0,0,0)

Using the above code I got weird results, changing

 If (pix And $FFFFFF)=maskcol WritePixelFast x,y,(pix Or $FF000000) Else WritePixelFast x,y,0 
to
 If (pix And $FFFFFF)=maskcol WritePixelFast x,y,0 Else WritePixelFast x,y,(pix Or $FF000000) 


Fixed it right up :)
Good work 0DFEx!

Jees- I let you in on a bit of info about alpha values, now you become the master! Maybe I should start testing stuff properly. Thanx John. : )

Noticed something else I forgot to mention
The code below reads and writes from the texture buffer, before there was an error

Test your code 0DFEx :P

[Code]
Function do_mask(texture,maskr=0,maskg=0,maskb=0)
maskcol=(maskr Shl 16)+(maskg Shl 8)+maskb
LockBuffer TextureBuffer(texture)
For x=0 To TextureWidth(texture)-1
For y=0 To TextureHeight(texture)-1
pix=ReadPixelFast(x,y,TextureBuffer(Texture))
If (pix And $FFFFFF)=maskcol WritePixelFast x,y,0,TextureBuffer(Texture) Else WritePixelFast x,y,(pix Or $FF000000),TextureBuffer(Texture)
Next
Next
UnlockBuffer TextureBuffer(texture)
End Function

[/Code]

Hey that is a great function!
And very useful in future applications!

Still, I have some problems. I am now using the "CyBeRGoth" version of the do_mask function :)

	b\texture=CreateTexture(128,64,4)
	SetBuffer TextureBuffer(b\texture)
	ClsColor 0,0,0
	Cls
	Color 5,5,5
	drawText(5,5,128,64,theText$,4,0)	
	do_mask(b\texture,0,0,0)
	Color 255,255,255


second try:

	b\texture=CreateTexture(128,64,4)
	SetBuffer TextureBuffer(b\texture)
	Color 5,5,5
	Text 0,0,"HELLO"	
	do_mask(b\texture,0,0,0)
	Color 255,255,255


Okay: so I create a texture. I tried CreateTexture(128,64,2) and CreateTexture(128,64,4)
Then I say: clear the area with BLACKness (second try I removed it). Then draw text with color 5,5,5.
Then mask the texture (make 0,0,0 transparent)
(ofcourse, and then I texture the entity)

But...I see nothing. Nada :(
What am I doing wrong here?

Maybe try adding this step
 TempText=CreateImage(128,64)

This creates an imagebuffer (make it the same size as your texture.

Then when you want to put your text it in
SetBuffer ImageBuffer(TempText)
Color 5,5,5
Text 0,0,"HELLO"	
CopyRect 1,0,128,64,0,0,ImageBuffer(TempText),TextureBuffer(b\texture)
do_mask(b\texture)


That should work

I Think there is just a problem if you try and do it straight to the texture buffer, but this way you are copying from the temp imagebuffer to the texturebuffer.

Wooooaaah that worked like a charm!!! Thanks.

Unfortunately it slows the game down (flicker)

Cool :)

You should only have to update the texture whenever the text changes in your game, not every time the game loops

Yes, I do :-)
When the user presses [ENTER] the texture is created on the fly (a text balloon above the players' head)

I think you need a different method to do it in your main loop. Copying buffers and even plain old text commands can really slow stuff down. Create a texture before your main loop with all the letters of the alphabet on it.To display your text create a load of quads (one per letter) in a single surface textured with your alphabet, and modify the uv co-ords of the quads to display your message. I'm sure someone out there will already have done something similar. Anyone?

hmmm that sounds like a hard solution :)

Guys,

I can't get it to work! What's wrong with the following:

Graphics3D 640,480 
SetBuffer BackBuffer() 

camera=CreateCamera() 

light=CreateLight() 
RotateEntity light,90,0,0 

cube=CreateCube() 
PositionEntity cube,0,0,5 

;;;;;;;;;;;
    
TempText=CreateImage(256,256)
texture=CreateTexture(256,256,4)

SetBuffer ImageBuffer(TempText)
ClsColor 0,0,0
Cls
Color 250,0,0
Rect 10,10, 100,100, 1
Color 255,255,255
Text 0,0,"TESTING..."	
CopyRect 0,0,256,256,0,0,ImageBuffer(TempText),TextureBuffer(texture)
do_mask(texture, 0,0,0)

;;;;;;;;;;;

EntityTexture cube,texture

SetBuffer BackBuffer()

While Not KeyDown( 1 ) 

  pitch#=0 
  yaw#=0 
  roll#=0 

  If KeyDown( 208 )=True Then pitch#=-1 
  If KeyDown( 200 )=True Then pitch#=1 
  If KeyDown( 203 )=True Then yaw#=-1 
  If KeyDown( 205 )=True Then yaw#=1 
  If KeyDown( 45 )=True Then roll#=-1 
  If KeyDown( 44 )=True Then roll#=1 

  TurnEntity cube,pitch#,yaw#,roll# 

  RenderWorld 
  Flip 

Wend 

End


Function do_mask(texture,maskr=0,maskg=0,maskb=0)
	maskcol=(maskr Shl 16)+(maskg Shl 8)+maskb
	LockBuffer TextureBuffer(texture)
	For x=0 To TextureWidth(texture)-1
		For y=0 To TextureHeight(texture)-1
			pix=ReadPixelFast(x,y,TextureBuffer(Texture))
			If (pix And $FFFFFF)=maskcol WritePixelFast x,y,0,TextureBuffer(Texture) Else WritePixelFast x,y,(pix Or $FF000000),TextureBuffer(Texture)
		Next
	Next
	UnlockBuffer TextureBuffer(texture)
End Function


The code inbetween the ;;;;;;;;; sections is the actual texture based stuff. Any help will do!?!

Why isn't the cube transparent? I want to see all 6 of the sides!

It works this way,
do you need the texture to be masked? because that's the problem, if you use flags 1+2 then there is no problem, this way you don't even need the "do_mask()" function, I think :)

test this:


Graphics3D 640,480 

camera=CreateCamera() 
	CameraClsColor camera,50,50,50

light=CreateLight() 
RotateEntity light,90,0,0 

cube=CreateCube() 
	PositionEntity cube,0,0,3
	EntityFX cube,1+16

;;;;;;;;;;;
texture=CreateTexture(256,256,1+2)

ClsColor 0,0,0
Cls
	For r=1 To 10
	Color Rand(100,255),Rand(100,255),Rand(100,255)
	Rect Rand(10,64),Rand(10,64),Rand(20,100),Rand(20,100),False
	Next

Color 255,255,255
	For t=1 To 20
	Text Rand(10,200),Rand(10,200),"TESTING..."	
	Next
	
CopyRect 0,0,256,256,0,0,BackBuffer(),TextureBuffer(texture)
;;;;;;;;;;;

EntityTexture cube,texture


While Not KeyDown( 1 ) 

  pitch#=0 
  yaw#=0 
  roll#=0 

  If KeyDown( 208 )=True Then pitch#=-1 
  If KeyDown( 200 )=True Then pitch#=1 
  If KeyDown( 203 )=True Then yaw#=-1 
  If KeyDown( 205 )=True Then yaw#=1 
  If KeyDown( 45 )=True Then roll#=-1 
  If KeyDown( 44 )=True Then roll#=1 

  TurnEntity cube,pitch#,yaw#,roll# 

  RenderWorld 
  Flip 

Wend 

End



Sorry, but the above code doesn't work! Any other suggestions?

JPJones- your code worked, there was just nothing behind the object to see thru 2.

Try putting this before your 'Setbuffer backbuffer()' line:
EntityFX cube,16

0DFEx: Thanks!!!