Color Keys in ID3DXSprite

Started by
6 comments, last by Programmer16 18 years, 9 months ago
When I call D3DXCreateTextureFromFile(), I set my color key to 0xff000000 This means I want any black to NOT be blittered, this would make black the transparent color. For some reason, this does not work. Can someone tell me how I can make a specific color not be copied when I blitter using ID3DXSprite::Draw()? Thank you!
Advertisement
Are you setting the alphablend states? You can do this in 2 ways:
1) Since you're using ID3DXSprite call ID3DXSprite::Begin() using D3DXSPRITE_ALPHABLEND.

2) Manually
g_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);g_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);g_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);


In the future, please post relevant code (it will make our job a lot easier.)
I apologize, didn't know I was required to post code since I asked for a method to do a specific job.

I used method 1 in your above list.

Still don't know how to do it.

Thanks for any help.
Quote:Original post by MrDoomMaster
I apologize, didn't know I was required to post code since I asked for a method to do a specific job.


No need to apologize, but if something isn't working then we need to see the code that you're using so that we can help.

But, is there anyway that I could see the code and maybe the image. I've written a test app and I'm having no problems.

If I came off as being rude I apologize.

Edit: Just for comparison, here is my code:
//------------------------------------------------------------------------------------------------// DISCLAIMER//------------------------------------------------------------------------------------------------#define D3D_DEBUG_INFO#include <windows.h>#include <d3d9.h>#include <d3dx9.h>#pragma comment(lib, "d3d9")#pragma comment(lib, "d3dx9d")#define SAFERELEASE(pObject)	if(pObject){pObject->Release();	pObject = 0;}//------------------------------------------------------------------------------------------------// Function prototypes//------------------------------------------------------------------------------------------------LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);bool Setup();//------------------------------------------------------------------------------------------------// Global variables//------------------------------------------------------------------------------------------------HWND				g_hWnd			= 0;IDirect3D9			*g_pDirect3D	= 0;IDirect3DDevice9	*g_pDevice		= 0;ID3DXSprite			*g_pSprite		= 0;IDirect3DTexture9	*g_pBaseImage	= 0;//------------------------------------------------------------------------------------------------// WinMain()//------------------------------------------------------------------------------------------------int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){	if(!Setup())		return 0;	D3DXCreateTextureFromFileEx(g_pDevice, "test.bmp", D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0xff000000, 0, 0, &g_pBaseImage);	MSG Msg;	ZeroMemory(&Msg, sizeof(MSG));	while(1)	{		if(PeekMessage(&Msg, 0, 0, 0, PM_REMOVE))		{			if(Msg.message == WM_QUIT)				break;			TranslateMessage(&Msg);			DispatchMessage(&Msg);		}		else		{			g_pDevice->Clear(0, 0, D3DCLEAR_TARGET, 0xffaaaaaa, 1.0f, 0);			g_pDevice->BeginScene();			g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);			g_pSprite->Draw(g_pBaseImage, 0, 0, 0, 0xffffffff);			g_pSprite->End();			g_pDevice->EndScene();			g_pDevice->Present(0, 0, 0, 0);		}		Sleep(0);	}	SAFERELEASE(g_pSprite);	SAFERELEASE(g_pBaseImage);	SAFERELEASE(g_pDevice);	SAFERELEASE(g_pDirect3D);	return 0;}LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam){	switch(nMsg)	{	case WM_CLOSE:	case WM_DESTROY:		{			PostQuitMessage(0);			return 0;		}	}	return DefWindowProc(hWnd, nMsg, wParam, lParam);}bool Setup(){	WNDCLASS WndClass;	ZeroMemory(&WndClass, sizeof(WNDCLASS));	WndClass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);	WndClass.hCursor		= LoadCursor(0, IDC_ARROW);	WndClass.hIcon			= LoadIcon(0, IDI_APPLICATION);	WndClass.hInstance		= GetModuleHandle(0);	WndClass.lpfnWndProc	= WndProc;	WndClass.lpszClassName	= "Bitmask Generator";	if(!RegisterClass(&WndClass))		return false;		g_hWnd = CreateWindowEx(0, WndClass.lpszClassName, WndClass.lpszClassName, WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, 0, 0, GetModuleHandle(0), 0);	if(!g_hWnd)		return false;	RECT Rect = {0, 0, 800, 600};	AdjustWindowRectEx(&Rect, WS_OVERLAPPEDWINDOW, TRUE, 0);	MoveWindow(g_hWnd, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top, FALSE);	ShowWindow(g_hWnd, SW_SHOWNORMAL);	g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);	if(!g_pDirect3D)		return false;	D3DPRESENT_PARAMETERS PresentParams;	ZeroMemory(&PresentParams, sizeof(D3DPRESENT_PARAMETERS));	PresentParams.BackBufferWidth	= 800;	PresentParams.BackBufferHeight	= 600;	PresentParams.BackBufferFormat	= D3DFMT_A8R8G8B8;	PresentParams.hDeviceWindow		= g_hWnd;	PresentParams.SwapEffect		= D3DSWAPEFFECT_DISCARD;	PresentParams.Windowed			= TRUE;	if(FAILED(g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams, &g_pDevice)))		return false;	if(FAILED(D3DXCreateSprite(g_pDevice, &g_pSprite)))		return false;	return true;}

And the image:
Hi,Guys.I felt some kind atmosphere to help each other.I come from China,where is lack of such communication in reality.So I come here.And I just reviewed my understanding of the use of D3DXSPRITE.Thanks Programmer16 and all the guys!
I am a Chinese spare time game developer and I hope to make mores friends to talk about game developing!
Okay, below is my function I use for blittering. This is a member of a class, but most of the variables should be evident.

int CBitmap::Blitter(int dest_x, int dest_y, RECT* source){    if(!m_Display->IsInitialized())        return 0;    if(!m_Loaded)        return 0;    if(m_Sprite->Begin(D3DXSPRITE_ALPHABLEND) != S_OK)        return 0;    if(m_Sprite->Draw(m_Texture, source, 0, &D3DXVECTOR3((float)dest_x,        (float)dest_y, 0.0), 0xffffffff) != S_OK)    {        return 0;    }    m_Sprite->End();    return 1;}


Below you will find the code I use to initialize the texture and the sprite.

    if(D3DXGetImageInfoFromFile(Path, &m_TexInfo) != D3D_OK)        return 0;    if(D3DXCreateTextureFromFileEx(m_Display->GetDevice(), Path, m_TexInfo.Width,        m_TexInfo.Height, 0, 0, m_TexInfo.Format, D3DPOOL_DEFAULT, D3DX_FILTER_NONE,        D3DX_DEFAULT, m_ColorKey, 0, 0, &m_Texture) != D3D_OK)    {        return 0;    }    if(D3DXCreateSprite(m_Display->GetDevice(), &m_Sprite) != S_OK)        return 0;


I can't post an image of what it is doing exactly, but I can describe it. I have a basic 64x64 sprite I'm blittering to my backbuffer chain. The image in the middle is a yellow circle, the rest of the square is black (this is my transparent color). The only thing that should appear is the yellow circle and the black area around it should not be visible.

Thank you!
Alright guys, I figured the problem out, thanks to Programmer16's code example, I did a little bit of comparison.

The problem was that when I loaded my texture, I didn't set the format to D3DFMT_A8R8G8B8. I set the format to the one that I received when I read the information on the png.

My final question:

Is there a way to set the color key AFTER you've loaded the texture? I would like to be able to do this, since later on I may change my color key dynamically.

Thank you!
I'm not positive but I don't think that you can. I've been using multitexturing for this, using bitmasks. I'll keep looking (I thought I saw something a couple years ago, but I can't remember.)

Another choice would be to release the texture and reload it which the different colorkey, but this would be slow.

Edit: Just out of curiosity, why are would you need to change the color key of a texture while the app is running? For this to take effect you would have to reload the texture (unless you already have 2 colorkeys), at which point you could specify a different colorkey.

Edit 2: I was looking at your code and I thought that I'd point out that you shouldn't call ID3DXSprite::Begin() or End() for each image, you're supposed to keep calls to these to a minimal (I've never gone about 2 calls to each.) IIRC this screws up ID3DXSprite's batching and texture sorting.

Edit 3: Why don't you just make images that have an alpha channel? If you don't know how/don't have the software I just made a tool that takes in a regular 24bit bmp and turns it into a dds file with an alpha channel. You can even select the color that you want to be transparent.

This topic is closed to new replies.

Advertisement