Page 1 of 1

ITexture and EMT_TRANSPARENT_ADD_COLOR

Posted: Wed Apr 29, 2009 3:44 pm
by tomhancocks
I've tried looking through the documentation on this one, and short of creating a 3D object and applying the Texture too it I can't figure out how to apply this flag to an ITexture.

Basically the game I'm creating uses a strange mix of 2D and 3D graphics. In the background is a pseudo 2d star field created with Billboards. These and spaced out along the z axis so that when they move they appear to move at different speeds giving the illusion of depth.

I then have a 3D layer. Planets, Particle effects and Nebula are going to get rendered in this layer.

Finally I have the 2D layer where ships, weapons and everything else is going. I've got the ships drawing nicely, extracting relevant sprites etc. The problem is the after burner effects. They need to look as if they are lighting things, not just solid blocks of colour. So how/is it possible to apply the EMT_TRANSPARENT_ADD_COLOR flag to an ITexture when you draw it via 2D methods.

Tom

Posted: Wed Apr 29, 2009 4:59 pm
by hybrid
ADD_COLOR is not supported by the 2d methods, only vertex alpha and alpha channel. The latter should work here as well, though. Just use your favorite painting program and let it create alpha channels from the black areas of your images.

Posted: Wed Apr 29, 2009 8:29 pm
by tomhancocks
hmm, ok.

Well since then I've noticed something that I'm not sure if its a bug or not. If 2 2D images are overlapping the bottom one is clipped, even after an alpha channel is applied.

I've applied an alpha channel with the following lines.

this->player_ship = this->driver->getTexture( shipTexture );
driver->makeColorKeyTexture(this->player_ship, core::position2d<s32>(0,0));

The code is based on the examples. The following image shows what's happening. The stars are been rendered in 3d, as explained in my first post, and you can see with the right hand sprite that alpha is definitely being applied, but its still clipping the left sprite.

Image

Appologies for the EV Nova graphics, have not yet got my own graphics sorted, want to get the engine out of the way first.

Posted: Thu Apr 30, 2009 7:44 am
by hybrid
How does your render loop look like?

Posted: Thu Apr 30, 2009 8:23 am
by tomhancocks
The actual rendering is split across several classes, specific classes rendering specific aspects.

The actual loop (as it stands now)

Code: Select all

// Run Loop
	s32 lastFPS;
	while (device->run()) {
		driver->beginScene(true, true, video::SColor(0,0,0,0));
		
		s32 fps = driver->getFPS();
		if (lastFPS != fps) {
			core::stringw str = L"FPS: ";
			str += fps;
			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
		
		player->update();
		player->drawShip();
		
		smgr->drawAll();
		driver->endScene();
	}
The drawShip() method is responsible for actually drawing the ship. For the test I simply just drew the same image twice, offsetting the second.

Code: Select all

void Player::drawShip() {
	if (this->rotation > 360) this->rotation -= 360;
	if (this->rotation < 0) this->rotation += 360;

	s32 spriteNumber = (s32)this->rotation / 10;
	s32 spriteNumberY = 0;

	while (spriteNumber >= this->sprites_x) {
		spriteNumberY++;
		spriteNumber -= this->sprites_x;
	}
	
	s32 x = this->ship_width * spriteNumber;
	s32 y = this->ship_height * spriteNumberY;
	
	this->driver->draw2DImage(this->player_ship, 
						  core::position2d<s32>((WIDTH - this->ship_width)/2, (HEIGHT - this->ship_height)/2), 
						  core::rect<s32>(x, y, x+this->ship_width, y+this->ship_height));
	this->driver->draw2DImage(this->player_ship, 
						  core::position2d<s32>((WIDTH)/2, (HEIGHT - this->ship_height)/2), 
						  core::rect<s32>(x, y, x+this->ship_width, y+this->ship_height));
}

Posted: Thu Apr 30, 2009 8:48 am
by hybrid
Ok, here's the correct order and params:
First draw 3d stuff (background), then draw 2d stuff (sprites).
Put your update method call outside the render part (before beginScene), because you will otherwise stall the pipeline.
Tell draw2DImage to use the alpha channel (right now it's just not visible because the transparent part is drawn black):

Code: Select all

draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
                        const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect =0,
                        SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false)
So add the following three params: 0, 0xffffffff, true
Not the final true, as it will enable alpha channel :!:

Posted: Thu Apr 30, 2009 9:14 am
by tomhancocks
Thats working better. I've added the after burner effect to the ship now, but with out the additive blend effect its looking a little strange. I think I will tinker around and devise a way of doing that, because I absolutely need it in the 2d graphics for this game.

edit: Just a quick screen shot to indicate the kind of thing i'm meaning, 'cause I'm not 100% certain I'm explaining myself correctly :P

Image

I can get the blend mode on the right all well and good, but its the one on the left which I'm after.[/img]

Posted: Thu Apr 30, 2009 11:00 am
by hybrid
You could use a particle system to get this effect, put it into your sprites animation with a painting tool, or you use a 3d quad with additive transparency and ender that on top of the sprites.