Special Effects Overlay

Started by
20 comments, last by stenny 16 years, 11 months ago
Wow guys! Thanks!

I didn't think it'd be that easy, just setting renderstates. I thought I had to go through parsing the grayscale or something. Anyway, I'm going to bed now, but I'll try tommorow and say if it works. Thanks!

-Stenny

[Edited by - stenny on May 24, 2007 8:59:25 AM]
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel
Advertisement
Ok. It's doing something, and it's some things I sorta want, but it's correct. This is what I got, with all things set like you guys told me to:



It's doing nothing. This is what I got when I did nót set back to the old alpha:



And this is what it looks like when I don't draw the overlay, and do not set back to the old alphasettings (D3DBLEND_SRCALPHA and INVSRCALPHA).



That's not completely right. The lights too intense and the other sprites are enlightened too.

-Stenny
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel
It looks like you're doing things in the wrong order. Here's how it should go:

1. Render the scene as you were in the first place.
2. Set the blend-mode to add.
3. Render the overlay.
4. Reset the blend-mode states to modulate.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
I'm almost sure that's what I'm doing! I'll check when I get home.

-Stenny
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel
You don't want to add the original texture as-is. It's quite obvious that the original texture contains large areas of almost pure white, and adding pure white to any underlying colour will give you just more pure white. I'm not a 3D programmer though so I don't know the exact operation you need. There's probably some sort of scaling or overall alpha factor that needs to be inserted somewhere.
Ok, I'm almost there. There still one problem, and here's what I've done. I followed up the Admirals advice (thanks mate!) and double checked if I did everything in the right order. I did. Nonetheless, I placed the rendering of the overlay even fúrhter in the gameloop. Also, I did some scaling and this is what I got:



The left image has full alpha and the right, like, 15 %.

I don't want those ugly black lines on the outer edges of the light though.

Any ideas?

-Stijn
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel
Quote:Original post by Kylotan
You don't want to add the original texture as-is. It's quite obvious that the original texture contains large areas of almost pure white, and adding pure white to any underlying colour will give you just more pure white. I'm not a 3D programmer though so I don't know the exact operation you need. There's probably some sort of scaling or overall alpha factor that needs to be inserted somewhere.

You're right, but I figured that that it would be easier to proxy-debug the blending problems without prematurely introducing an alpha factor. The easiest way to tone down the effect would be to set the colour of the quad to translucent white. Something like 0x40FFFFFF0x40404040 would do nicely.

Stijn, that last image looks like a step backwards to me. The second picture in your previous post was almost correct, but the blending mode wasn't being correctly reset. From the looks of things, you're currently telling D3DXCreateTextureEx to pseudo-colour-key out opaque black from the texture, and blending the texture under regular alpha-modulation. I see no evidence of additive blending.

You're going to have to paste us your code. Try to keep it short, but make sure you include everything pertaining to texture-loading, geometry creation, blending-state switches and rendering.

Admiral

Edit: Fixed that colour-value to work with the additive blend-mode.

[Edited by - TheAdmiral on May 25, 2007 1:02:30 PM]
Ring3 Circus - Diary of a programmer, journal of a hacker.
Well, I've got a complete graphical engine running underneath this (I know what I'm doing, I just have never looked into Blending and Alpha's). I'll try to keep this shitload of code as short as possible [wink].

First, Direct3D9 COM object is created. It is then set (registered);

- windowed
- D3DFMT_X8R8G8B8
- D3DSWAPEFFECT_DISCARD
- HAL
- Alpha Blending and Alpha Testing is now set off (standard function), but those will be turned on later on.

End of the SetMode() function. Now EnableAlphaBlending and EnableAlphaTesting are called again, but this time they're Enabled (not disabled):

EnableAlphaBlending(bool Enable = true, DWORD Src = D3DBLEND_SRCALPHA, DWORD Dest = D3DBLEND_INVSRCALPHA){	if(!m_pD3DDev) { return false; }	if(FAILED(m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, Enable))) { return false; }	if(Enable)	{		m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, Src);		m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, Dest);		m_Log->Out("Enabled ALPHA BLENDING\n");	} else {		m_Log->Out("Disabled ALPHA BLENDING\n");	}	return true;}bool cNGraphics::EnableAlphaTesting(bool Enable = true){	if(!m_pD3DDev) { return false; }	if(FAILED(m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, Enable))) { return false; }	if(Enable)	{		m_pD3DDev->SetRenderState(D3DRS_ALPHAREF, 0x08);		m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);		m_Log->Out("Enabled ALPHA TESTING\n");	} else {		m_Log->Out("Disabled ALPHA TESTING\n");	}	return true;}


They're called with no arguments set, thus the standard arguments are taken. DirectInput and the MapEngine are set up (of no relevance here). While parsing through a map-file, an cAnim class is loaded, holding the overlay (Lightbeams.png):

class cNAnim{private:	cNGraphics			*m_Graphics;	LPDIRECT3DTEXTURE9	m_pTexture;	std::string			m_Name;	DWORD				m_Width, m_Height;	int				m_OriginX, m_OriginY, m_FrameWidth, m_FrameHeight, m_Columns, m_Rows;	int				m_StartLoop, m_EndLoop;	int				m_NumFrames;	int		m_Frame;	float		m_Speed;	DWORD		m_Timer, m_Elapsed, m_FrameTimer;public:	cNAnim();	~cNAnim();	bool	Load(cNGraphics *Graphics, char *Filename, int NumFrames, int FrameWidth, int FrameHeight, int StartLoop = 0, int EndLoop = -1, DWORD Transparent = 0, float Speed = 0, D3DFORMAT Format = D3DFMT_UNKNOWN);	bool	LoadEx(cNGraphics *Graphics, char *Filename, int NumFrames, int Framewidth, int FrameHeight, int OriginX, int OriginY, int StartLoop = 0, int EndLoop = -1, DWORD Transparent = 0, float Speed = 0, D3DFORMAT Format = D3DFMT_UNKNOWN);	bool	Free();	bool	Blit(int DestX, int DestY, DWORD Color = 0xFFFFFFFF, int SrcX = 0, int SrcY = 0, int Width = 0, int Height = 0, float XScale = 1.0f, float YScale = 1.0f);	bool	Update();	bool	IsLoaded();	bool	AnimEnd();	bool	SetSpeed(float Speed);	bool	SetFrame(int Frame);	/* A whole lotta 'Get' functions */};bool cMap::SetOverlay(std::string Filename, int Alpha){	if(Filename == "") { return false; }	cNAnim *Overlay	= new cNAnim;	Overlay->Load(m_Graphics, const_cast<char*>(Filename.c_str()), 1, 320, 240, 0, -1, 0x00000000, 10);	m_Overlay	= Overlay;	return true;}bool cNAnim::Load(cNGraphics *Graphics, char *Filename, int NumFrames, int FrameWidth, int FrameHeight, int StartLoop, int EndLoop, DWORD Transparent, float Speed, D3DFORMAT Format){	Free();	if(!(m_Graphics = Graphics)) { return false; }	if(!m_Graphics->GetDeviceCOM()) { return false; }	if(!Filename) { return false; }	if(FAILED(D3DXCreateTextureFromFileEx(Graphics->GetDeviceCOM(), Filename, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0,										  Format, D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE, D3DX_FILTER_TRIANGLE, Transparent,										  NULL, NULL, &m_pTexture)))	{ return false; }	m_Name		=	Filename;	if(!FrameWidth)	{		m_FrameWidth = GetWidth();	} else {		m_FrameWidth = FrameWidth;	}	if(!FrameHeight)	{		m_FrameHeight = GetHeight();	} else {		m_FrameHeight = FrameHeight;	}	m_Width = GetWidth();	m_Height = GetHeight();	m_OriginX = 0;	m_OriginY = 0;	m_Columns   = m_Width / m_FrameWidth;	m_Rows		= m_Height / m_FrameHeight;	if(!(m_NumFrames = NumFrames)) { return false; }	if(m_NumFrames == -1) { m_NumFrames = m_Columns * m_Rows; }	m_StartLoop = StartLoop;	m_EndLoop = EndLoop;	if(m_StartLoop < 0) { m_StartLoop = 0; }	if(m_EndLoop < 0) { m_EndLoop = m_NumFrames; }	if(m_StartLoop > m_NumFrames) { m_StartLoop = 0; }	if(m_EndLoop > m_NumFrames) { m_EndLoop = m_NumFrames; }	SetSpeed(Speed);	return true;}


SetOverlay("Data/Images/Overlay/Lightbeams.png", 1) is called. cNAnim::Load is called, and the image is loaded in. Now for the last three functions:

bool cMap::Render(int RenderX, int RenderY, DWORD Color, int StartX, int StartY, int EndX, int EndY){	int ForX, ForY;	if(StartX < 0 || StartY < 0) { return false; }	if(StartX >= m_Columns || StartY >= m_Rows) { return false; }	if(EndX > m_Columns) { EndX = m_Columns; }	if(EndY > m_Rows) { EndY = m_Rows; }	if(!EndX) { EndX = m_Columns; }	if(!EndY) { EndY = m_Rows; }	for(ForY=StartY;ForY<EndY;ForY++)	{		for(ForX=StartX;ForX<EndX;ForX++)		{			RenderPile(&m_Ground[ForX][ForY], RenderX, RenderY, Color);		}	}	return true;}bool cMap::RenderOverlay(){	if(m_Overlay)	{		m_Graphics->EnableAlphaBlending(true, D3DBLEND_ONE, D3DBLEND_ONE);		m_Overlay->Blit(0, 0, 0x44FFFFFF, 0, 0, 0, 0, 1, 1);		m_Graphics->EnableAlphaBlending(true, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);	}	return true;}bool cNAnim::Blit(int DestX, int DestY, DWORD Color, int SrcX, int SrcY, int Width, int Height, float XScale, float YScale){	RECT			Rect;	LPD3DXSPRITE	pSprite;	D3DXMATRIX		matTemp;	int			FSrcX, FSrcY;	if(!m_pTexture || !m_Graphics || !(pSprite = m_Graphics->GetSpriteCOM())) { return false; }		FSrcX = (m_Frame % m_Columns) * m_FrameWidth;	FSrcY = (m_Frame / m_Columns) * m_FrameHeight;	if (Width == 0 || Height == 0)	{		Rect.left = FSrcX;		Rect.top = FSrcY;		Rect.right = FSrcX + m_FrameWidth;		Rect.bottom = FSrcY + m_FrameHeight;	} else {		Rect.left = FSrcX + SrcX;		Rect.top = FSrcY + SrcY;		Rect.right = FSrcX + SrcX + Width;		Rect.bottom = FSrcY + SrcY + Height;	}	D3DXMatrixIdentity(&matTemp);	D3DXMatrixScaling(&matTemp, XScale, YScale, 1.0f);	if(FAILED(pSprite->SetTransform(&matTemp))) { return false; }	if(FAILED(pSprite->Draw(m_pTexture, &Rect, NULL, &D3DXVECTOR3((float)DestX - m_OriginX, (float)DestY - m_OriginY, 0), Color))) { return false; }	Update();	return true;}


The map is render (cMap::Render()), and after that function (yes, immediately after Render()), RenderOverlay() is called. The overlay is rendered, and you get the effect of the above two images. Previously, I put the code inside RenderOverlay() at the end of Render(), and I got the former three pics.

I hope that's enough![wink]

-Stijn

[Edited by - stenny on May 25, 2007 12:27:31 PM]
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel
The cNAnim::Load doesn't match the overload you are calling (it's one parameter short). In particular, I don't know what format you're creating the texture as. The whole setup is rather more complicated than I expected and its difficult to know what state the samplers and blending engine will be in at any moment, so there are lots of things to go wrong.

Anyway, call me a cop-out but I'm gonna abandon this route now. Considering that you're using a fairly high-level engine design, it's in your interest to minimise state-changes. For this reason, you're probably best off using alpha-blending like everyone else suggested [rolleyes]. I've tidied the image up a little and coded it into the alpha channel of a greyscale png. I've increased the colour-depth to 8-bits so as to remove that nasty dithering, so the texture is a little bigger now (17k as opposed to 7).



You won't be able see the alpha-blending here if you're using IE6, as it can't handle PNGs (I think IE7 and Firefox are fine), but it's there all the same. To draw this, you need only enable alpha-blending (not testing). I hope you have more success this time.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Dude, you're my hero. Many, many thanks!


(It's cut off on the right side because it's not scaled yet)

Now I only need to know how you edited those alpha values, and I'm ready to go!

Thanks again! [smile]

-Stijn
What do I expect? A young man's quest to defeat an evil sorceror while discovering the truth of his origins. A plucky youngster attended by her brutish guardian. A powerful artifact which has been broken into a small number of artifactlets distributed around the world.What do I want? Fewer damn cliches. - Sneftel

This topic is closed to new replies.

Advertisement