Game Development Community

Alpha image/Bitmap use

by Neel "Roy Fokker" Raiyani · in Torque Game Engine · 11/09/2002 (7:35 am) · 14 replies

poc.3dmax.org//Temp/example.gif
I would like to know how i can accomplise that in torque.

Background Image is say your scene or in-game view

image1 is a bitmap on the hud, image 2 masks image 1 so that only a certain part of it is visible on the screen.

Now before you tell me its Easy just use a Png with Alpha. Image1 already has an alpha layer, i want another alpha layer so that i can move image one around and at the same time leave only a part of it visible.

A good overview on how i can do that would be very helpful. an Algorithm would be better.

thankx for any insights

#1
11/09/2002 (10:16 am)
almost sounds like you are speaking of a stencil buffer or a mask of sorts....
#2
11/09/2002 (12:38 pm)
i am not aware of the technical jargon which is why i made the image to get the point across
#3
11/09/2002 (2:55 pm)
Neel,

To answer your question. There is no non-technical way to answer this technical problem.

If you require the technical solution then you will find that you can achieve this simply with multi-texture blending. There is no non-technical way to provide this information short of writing the code for you.

- Melv.
#4
11/09/2002 (3:05 pm)
Multi-Texture Blending huh,
ok, i'll see what i can find on it.
their is no simple explaination on how it would work with tge?
#5
11/09/2002 (3:29 pm)
It's a hardware accellerated technique of texturing on the graphics card. It really does depending on what you want to render but if you're not a programmer or haven't done any graphics programming before then you've got alot of stuff to learn if you want to do it all yourself.

OpenGL makes this quite painless and using something like my fxRenderObject will make it easier to see it in action. I also believe that there is a multi-texture resource somewhere.

If the image is fairly static then you could manipulate GBitmaps to achieve this masking and finally render it to the screen. This would take place on the CPU rather than the GPU and so would not be hardware accellerated.

- Melv.
#6
11/09/2002 (4:46 pm)
i just found out how to do texture blending in OpenGL. so now i know how to blend 2 textures

What i am trying to do in Torque is i am using a Map Ctrl(Frank Bigone), the default shape for the map ctrl is square and what i want is a circle.

I thought best way to do that would be to use a image as a mask over the map ctrl to make a specific shape visible.
#7
11/10/2002 (3:35 am)
Neel,

You alternately may want to look at the Torque supported OpenGL extension "ext_texture_env_combine" which allows for *much* more control over texture blending although it is mor complex to use and information on it's usage is not wide-spread. Using this you can control the colour/alpha seperately etc.

If you need any specific help with the OpenGL/GUI Stuff then please just ask.

All the best,

- Melv.
#8
11/10/2002 (7:26 am)
ok i tried a few things, but i can't get it to work, it seems to be colour burning the image1 instead of masking image1 with image2

this is the code i used

//----------------------------------------------------------------------------
void dglBlendBitmaps(TextureObject* texture,
					const RectI& dstRect,
					const RectI& srcRect,
					TextureObject* maskTexture,
					const RectI& stretch)
{
	AssertFatal(texture != NULL, "GSurface::BlendBitmaps: NULL Handle (texture)");
	AssertFatal(maskTexture != NULL, "GSurface::BlendBitmaps: NULL Handle (maskimage)");
	if(!dstRect.isValidRect())
		return;
	AssertFatal(srcRect.isValidRect() == true, "GSurface::BlendBitmaps: routines assume normal rects");

	glDisable(GL_LIGHTING);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	//--------------------------------Masking Part to the blend-------------------------
	//----------------------Mask Only
	RectI subRegion(0, 0, maskTexture->bitmapWidth, maskTexture->bitmapHeight);
	//-------------------------------
	F32 mtexLeft	= F32(subRegion.point.x) / F32(maskTexture->texWidth);
	F32 mtexRight	= F32(subRegion.point.x + subRegion.extent.x) / F32(maskTexture->texWidth);
	F32 mtexTop		= F32(subRegion.point.y) / F32(maskTexture->texHeight);
	F32 mtexBottom	= F32(subRegion.point.y + subRegion.extent.y) / F32(maskTexture->texHeight);
	F32 mScreenLeft		= stretch.point.x;
	F32 mScreenRight	= stretch.point.x + stretch.extent.x;
	F32 mScreenTop		= stretch.point.y;
	F32 mScreenBottom	= stretch.point.x + stretch.extent.y;

	glBlendFunc(GL_DST_COLOR,GL_ZERO);
	glBindTexture(GL_TEXTURE_2D, maskTexture->texGLName);

	glColor4ub(sg_bitmapModulation.red,
			sg_bitmapModulation.green,
			sg_bitmapModulation.blue,
			sg_bitmapModulation.alpha);

	glBegin(GL_TRIANGLE_FAN);
		glTexCoord2f(mtexLeft, mtexBottom);
		glVertex2f(mScreenLeft, mScreenBottom);

		glTexCoord2f(mtexRight, mtexBottom);
		glVertex2f(mScreenRight, mScreenBottom);

		glTexCoord2f(mtexRight, mtexTop);
		glVertex2f(mScreenRight, mScreenTop);

		glTexCoord2f(mtexLeft, mtexTop);
		glVertex2f(mScreenLeft, mScreenTop);
	glEnd();
//------------------------------------End Masking part----------------------------------

//-------------------------------------Texture part-------------------------------------
	glBindTexture(GL_TEXTURE_2D, texture->texGLName);
	glBlendFunc(GL_ONE,GL_ONE);

	F32 texLeft		= F32(srcRect.point.x) / F32(texture->texWidth);
	F32 texRight	= F32(srcRect.point.x + srcRect.extent.x) / F32(texture->texWidth);
	F32 texTop		= F32(srcRect.point.y) / F32(texture->texHeight);
	F32 texBottom	= F32(srcRect.point.y + srcRect.extent.y) / F32(texture->texHeight);
	F32 screenLeft	= dstRect.point.x;
	F32 screenRight	= dstRect.point.x + dstRect.extent.x;
	F32 screenTop	= dstRect.point.y;
	F32 screenBottom = dstRect.point.y + dstRect.extent.y;

	glColor4ub(sg_bitmapModulation.red,
			 sg_bitmapModulation.green,
			 sg_bitmapModulation.blue,
			 sg_bitmapModulation.alpha);

	glBegin(GL_TRIANGLE_FAN);
		glTexCoord2f(texLeft, texBottom);
		glVertex2f(screenLeft, screenBottom);

		glTexCoord2f(texRight, texBottom);
		glVertex2f(screenRight, screenBottom);

		glTexCoord2f(texRight, texTop);
		glVertex2f(screenRight, screenTop);

		glTexCoord2f(texLeft, texTop);
		glVertex2f(screenLeft, screenTop);
	glEnd();
//---------------------------------------End Texture Part
	glDisable(GL_BLEND);
	glDisable(GL_TEXTURE_2D);
}
//-----------------------------------------------------------------------------------

Would be nice if some one could tell me what i am doing worng. the function itself is based on dglBitmapStretchSR and dglBitmapStretch.
the Result i get with the above is this
poc.3dmax.org//Temp/result.png
#9
11/10/2002 (8:15 am)
Neel,

If I understand the effect you want correctly then the code above will not work. It is using blending to texture twice but this is *not* multi-texturing as I described above.

I'm not about to explain in infinite detail how to do multi-texturing otherwise it would be pages of text but I will give you pointers which will hopefully get you started. There are loads of examples of multi-texturing on the net but you can also find it being used in my fluid rendering source code although this is a little too complex for a tutorial on the subject.

Before you read the follow, don't forget that you can alternatively manipulate the bitmaps at the pixel level on the CPU to achieve the effect you desire e.g. use a bitmap as a canvas by copying image1 into it and then masking it with image2 at the pixel level. This is done on the cpu and so if you are going to do this frequently then you'll have to be careful and watch the cpu load.

If you want to do this on the graphics card then you will need multi-texturing. Multi-texturing is the ability to send a single-set of vertex data and have multiple 'layers' of texturing applied using this data.

The problem with your approach can be described as follows...

Key:-
Fb = Frame Buffer (Screen)
I1 = Image1
I2 = Image2

The blending operations you are doing have no temporary storage and can only contain two components, Source and Destination e.g. each blending operation gets folded into the screen.

The effect you are achieving is ...

(Fb op I1) op I2

This results in you merging I1 into Fb and then doing an operation on the Fb with I2. If I understand you correctly, you require a masking operation of I1 op I2 followed by and operation on Fb as follows ...

(I1 op I2) op Fb.

This means that you want to mask I1 with I2 *before* you commit it to Fb. The only way you can do this is using multi-texturing.

Links...

nVidia Code
PPT Example

You will also find multi-texuring used throughout the Torque codebase.

You need to be looking at the usage of glActiveTextureARB and possibly glClientActiveTextureARB.

Don't forget to check for multi-texturing capability (including how many texture stages). If multi-texturing is available then you will *always* have at least two which should be all you need.

You will also want to look at the usage of ext_texture_env_combine which provides very powerful texture operations.

If you need more specifics then just ask.

Hope this helps,

- Melv.
#10
11/10/2002 (9:30 am)
I have some preliminary work done on problems like this. I've been a little too lazy to keep refining it lately... is there something specific you had in mind?
#11
11/10/2002 (7:50 pm)
/me ripping my hair out.

James May i ask to see what you did with that lighting thing that you created?
#12
11/11/2002 (8:09 am)
Well, it's not real lighting by a long shot. =)

But the blend sequence to recreate it is basically:

glBindTexture( Background Texture )
... Draw Geometry ...

glBindTexture( Flare Texture )
glBlendFunc( SRC_COLOR, DST_COLOR )
... Draw Geometry ...
#13
11/11/2002 (8:31 am)
its almost the same thing that i did, with a few changes to the blend func.

Regardless. going to try it with multi texturing as Melv has suggested. so far i am getting very odd results, its either all black or all transparent.
#14
04/29/2003 (5:53 am)
Hi everybody,

Hmmm, I've noticed the same problem as Neel, i.e. how to limit hud control to certain shape...
My question is: Is there any possibility to draw map control bitmap to some surface and then copy it to screen by blending with mask texture? I think, it would solve that problem, but unfortunatelly all dlgDrawXXX functions work directly on screen buffer (is it correct?)...

Thanks for any help...