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]
Special Effects Overlay
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
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
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
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
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
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
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]
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):
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):
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:
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]
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]
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
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
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement