Sign in to follow this  
Yola

Alpha chanel

Recommended Posts

Yola    100
Need to detect which object clicked. Every object have texture with alpha, can i check is click was on transparent pixel?

Now i save alpha lyaer as separate array by lock texture extract from it, but it seems to take much memory.

I use DirectX.

Share this post


Link to post
Share on other sites
Dawoodoz    461
The fastest way to sample a pixel from a texture is to have a copy of the texture on the CPU. The array getting the data must have the same color representation as the texture. You might want to use a boolean quad tree to save a lot of memory. To speed up loading time, you can save a boolean quad tree for each texture and delete the tree file when the edges has changed.

Here is the code for getting a rectangle from a texture to an array directly from my engine:
[code]
struct CPUSurface_Struct {
COLLECTION_STRUCT_DATA(CPUSurface)

ID3D11Texture2D* StagingBuffer;

// Index = X + (Y * Width)
// Size = Width * Height
D3DXVECTOR4* CPUContent;

// Dimensions
int Width;
int Height;
};

void EngineCore::CPUSurface_SetSize(CPUSurface_Struct* Surface, int NewWidth, int NewHeight, float Red, float Green, float Blue, float Alpha) {
if (NewWidth < 1 || NewHeight < 1) {
MQ->InsertMessage(L"CPUSurface_SetSize: A CPU surface can't have non positive dimensions.");
} else if (NewWidth > 8192 || NewHeight > 8192) {
MQ->InsertMessage(L"CPUSurface_SetSize: A CPU surface can't have dimensions larger than 8192.");
} else {

// Release any old data to avoid memory leaks
CPUSurface_Struct_Release(Surface);

// Store dimensions
Surface->Width = NewWidth;
Surface->Height = NewHeight;

// Allocate the CPU array
int Size = NewWidth * NewHeight;
Surface->CPUContent = new D3DXVECTOR4[Size];

// Fill the CPU array with a default value for deterministic behaviour.
CPUSurface_FillWithColor(Surface,Red, Green, Blue, Alpha);

// Create staging buffer
D3D11_TEXTURE2D_DESC StagedDesc = {
NewWidth,//UINT Width;
NewHeight,//UINT Height;
1,//UINT MipLevels;
1,//UINT ArraySize;
DXGI_FORMAT_R32G32B32A32_FLOAT,//DXGI_FORMAT Format;
1, 0,//DXGI_SAMPLE_DESC SampleDesc;
D3D11_USAGE_STAGING,//D3D11_USAGE Usage;
0,//UINT BindFlags;
D3D11_CPU_ACCESS_READ,//UINT CPUAccessFlags;
0//UINT MiscFlags;
};
m_pd3dDevice->CreateTexture2D( &StagedDesc, NULL, &Surface->StagingBuffer );
}
}

void EngineCore::CPUSurface_CopyRectFromDrawSurface(DrawSurface_Struct* Input_DrawSurface, CPUSurface_Struct* Output_CPUSurface, int SourceLeft, int SourceTop, int DestLeft, int DestTop, int Width, int Height) {
int i; int X; int Y;
ID3D11Texture2D* InputResource;
if (Input_DrawSurface->FinalSurface == true) {
MQ->InsertMessage(L"CPUSurface_CopyRectFromDrawSurface: The final draw surface can not be used with this method because it does not work like a regular draw surface.");
} else if (DestLeft < 0) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestLeft = %i < 0.",DestLeft); MQ->InsertMessage(MQ->messageBuffer);
} else if (DestTop < 0) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestTop = %i < 0.",DestTop); MQ->InsertMessage(MQ->messageBuffer);
} else if (SourceLeft < 0) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceLeft = %i < 0.",SourceLeft); MQ->InsertMessage(MQ->messageBuffer);
} else if (SourceTop < 0) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceTop = %i < 0.",SourceTop); MQ->InsertMessage(MQ->messageBuffer);
} else if (SourceLeft + Width > Input_DrawSurface->CurrentWidth) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceLeft + Width = %i > %i.",SourceLeft + Width,Input_DrawSurface->CurrentWidth); MQ->InsertMessage(MQ->messageBuffer);
} else if (SourceTop + Height > Input_DrawSurface->CurrentHeight) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: SourceTop + Height = %i < %i.",SourceTop + Height,Input_DrawSurface->CurrentHeight); MQ->InsertMessage(MQ->messageBuffer);
} else if (DestLeft + Width > Output_CPUSurface->Width) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestLeft + Width = %i < %i.",DestLeft + Width,Output_CPUSurface->Width); MQ->InsertMessage(MQ->messageBuffer);
} else if (DestTop + Height > Output_CPUSurface->Height ) {
swprintf_s( MQ->messageBuffer, L"CPUSurface_CopyRectFromDrawSurface: DestTop + Height = %i < %i.",DestLeft + Height,Output_CPUSurface->Height); MQ->InsertMessage(MQ->messageBuffer);
} else if (Input_DrawSurface->HasContent == false) {
// Save time if we already know the result
LoopForward(DestTop,Y,DestTop + Height - 1) {
LoopForward(DestLeft,X,DestLeft + Width - 1) {
Output_CPUSurface->CPUContent[X + (Y * Output_CPUSurface->Width)] = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
}
}
} else {
// Select all pixels
D3D11_BOX SrcBox;
SrcBox.left = SourceLeft; // Minimum X
SrcBox.right = SourceLeft + Width; // Maximum X
SrcBox.top = SourceTop; // Minimum Y
SrcBox.bottom = SourceTop + Height; // Maximum Y
SrcBox.front = 0; // Always 0 for 2D textures
SrcBox.back = 1; // Always 1 for 2D textures

// Get the texture pointer
if (Input_DrawSurface->HaveExtraColorBuffer == false || Input_DrawSurface->SwapState == true) {
InputResource = Input_DrawSurface->OriginalColorBuffer;
} else {
InputResource = Input_DrawSurface->ExtraColorBuffer;
}

// Copy the draw surface to the staging buffer
m_pImmediateContext->CopySubresourceRegion(Output_CPUSurface->StagingBuffer,0,0,0,0,InputResource,0,&SrcBox);

// Lock the memory
D3D11_MAPPED_SUBRESOURCE MappingResult;
m_pImmediateContext->Map(Output_CPUSurface->StagingBuffer,0,D3D11_MAP_READ,0,&MappingResult);

// Get the data
if (MappingResult.pData == NULL) {
MQ->InsertMessage(L"CPUSurface_CopyRectFromDrawSurface: Could not read the texture because the mapped subresource returned NULL.");
} else {
i = 0;
LoopForward(DestTop,Y,DestTop + Height - 1) {
LoopForward(DestLeft,X,DestLeft + Width - 1) {
Output_CPUSurface->CPUContent[X + (Y * Output_CPUSurface->Width)] = ((D3DXVECTOR4*)MappingResult.pData)[i];
i++;
}
}
}

// Unlock the memory
m_pImmediateContext->Unmap(Output_CPUSurface->StagingBuffer,0);
}
}
[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this