Jump to content
  • Advertisement
Sign in to follow this  
Arkanoid

Alpha channel

This topic is 2282 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How to setup textures alpha channel? I found only this:
LPDIRECT3DTEXTURE9 m_pTexture;

// Create an alpha texture
D3DXCreateTexture(m_d3dDevice, 128, 128, 0, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pTexture);

// Initialize the alpha channel
int yGrad, xGrad;
D3DLOCKED_RECT lockedRect;

if(SUCCEEDED(pTexture->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD )))
{
m_pRGBAData = new DWORD[128*128];
if( m_pRGBAData != NULL )
{
for( DWORD y=0; y < m_dwHeight; y++ )
{
DWORD dwOffset = y*m_dwWidth;
yGrad = (int)(((float)y/(float)m_dwWidth) * 255.0f);

for( DWORD x=0; x < m_dwWidth; x )
{
xGrad = (int)(((float)x/(float)m_dwWidth) * 255.0f);

DWORD b = (DWORD)(xGrad + (255 - yGrad))/2 & 0xFF;
DWORD g = (DWORD)((255 - xGrad) + yGrad)/2 & 0xFF;
DWORD r = (DWORD)(xGrad + yGrad)/2 & 0xFF;
DWORD a = (DWORD)(xGrad + yGrad)/2 & 0xFF;

lockedRect.pBits[dwOffset+x] = ((a<<24L)+(r<<16L)+(g<<8L)+(b));
x++;
}
}
}
pTexture->UnlockRect(&lockedRect);
}


m_pd3dDevice->SetTexture(0, m_pTexture);

// Texture stage states
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

m_pd3dDevice->SetTextureStage

but this sample doesn't work...

Share this post


Link to post
Share on other sites
Advertisement
IIRC render target usage is incompatible with managed pool allocation. Other than that, the code should generate a square texture with linear gradients for all channels, including alpha.

Note that texture scanline width (or Pitch) is not guaranteed to be same as width*bytesPerPixel; this code assumes that it is but this is often an incorrect assumption. The locked rect structure contains the Pitch field for this.

The [color=#000000]m_pRGBAData array is not needed; D3D will allocate (or give) the scratch space from system memory for you when you lock resources. The pointer to the scratch space is in the locked rect structure's pBits field.

The x loop counter is incremented in a funny way; usually, the incrementation is done in the "for" statement:

[font=courier new,courier,monospace]for (int x = 0; x < something; ++x) {}[/font]

Define "doesn't work".

Share this post


Link to post
Share on other sites


int yGrad, xGrad;
D3DLOCKED_RECT lockedRect;

if(SUCCEEDED(LOCATIONS.g_pMeshTextures->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD )))
{

for( DWORD y=0; y <lockedRect.Pitch ; y++ )
{
DWORD dwOffset = y*lockedRect.Pitch;
yGrad = (int)(((float)y/(float)lockedRect.Pitch) * 255.0f);

for( DWORD x=0; x < lockedRect.Pitch; x++ )
{
xGrad = (int)(((float)x/(float)lockedRect.Pitch) * 255.0f);

DWORD b = (DWORD)(xGrad + (255 - yGrad))/2 & 0xFF;
DWORD g = (DWORD)((255 - xGrad) + yGrad)/2 & 0xFF;
DWORD r = (DWORD)(xGrad + yGrad)/2 & 0xFF;
DWORD a = (DWORD)(xGrad + yGrad)/2 & 0xFF;

lockedRect.pBits[dwOffset+x] = ((a<<24L)+(r<<16L)+(g<<8L)+(b));

}
}
}
LOCATIONS.g_pMeshTextures->UnlockRect((UINT)&lockedRect);



// Texture stage states
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);


I have error one here:
lockedRect.pBits[dwOffset+x] = ((a<<24L)+(r<<16L)+(g<<8L)+(b));

Share this post


Link to post
Share on other sites
-The y coordinate range is 0...height-1. You are now writing past the allocated area, and if you're lucky, you get an access violation + crash your program.
-The pBits field is a void pointer; the compiler cannot determine the width of the elements automatically if you treat it as an array. Cast it to a unsigned char* before performing pointer arithmetic.
-The x coordinate should still span just the width of the texture; pitch can be the same or greater than width*bytes per pixel (you can't really assume anything else).
-Assuming x and y span the width and height of the texture respectively, the unsigned char (or byte) pointer for a 32-bit texel at x,y can be found as follows:

y * pitch + x * 4

...since each pixel is 4 bytes wide, assuming the format is a8r8g8b8, and each scanline is pitch bytes wide in memory. The byte pointer can be cast to UINT* so you can easily dereference a whole UINT. Alternatively, you can also write the argb data directly to the pointer by treating it as a byte array.

Share this post


Link to post
Share on other sites
blink.png well...looks like that i didn't understand anything....but no, something i understand, but not enough to write correct code...is there maybe a working sample about texture alpha? Or some lessons? I just need working code, cause trying to understand code, that don't work its hard...

Share this post


Link to post
Share on other sites
Alpha data is just an another byte in the texels (assuming a8r8g8b8), just like red, green and blue.

Do you understand the difference between "void*" and "unsigned char *" (or pointer to any data type), and how the pointer type affects the way the array element addresses are calculated? It is best to start from the language basics before doing more advanced stuff with D3D.

Share this post


Link to post
Share on other sites
[font=courier new,courier,monospace]for (uint y = 0; y < height; y++)[/font]
[font=courier new,courier,monospace]for (uint x = 0; x < width; x++)[/font]
[font=courier new,courier,monospace]{[/font]
[font=courier new,courier,monospace] unsigned char* pBytes = (unsigned char*)lr.pBits; // lr = D3DLOCKED_RECT you get from locking the texture[/font]
[font=courier new,courier,monospace] uint offset = y * lr.Pitch + x * 4; // as explained in earlier post[/font]
[font=courier new,courier,monospace] pBytes[offset] = alpha; // alpha, red, green, blue are unsigned chars 0...255[/font]
[font=courier new,courier,monospace] pBytes[offset + 1] = red;[/font]
[font=courier new,courier,monospace] pBytes[offset + 2] = green;[/font]
[font=courier new,courier,monospace] pBytes[offset + 3] = blue;[/font]
[font=courier new,courier,monospace]}[/font]

Share this post


Link to post
Share on other sites
I set pBytes[offset + 3] = 255;, cause if i understand correctly its must be alpha channel, but now i can see only black rectangles on textures.

pBytes[offset] = alpha; -hmm maybe not, cause i set it to 255 - and saw blue rectangles....

Share this post


Link to post
Share on other sites
Yea, the bytes are other way around (I used less than 1 minute to write the example loops) :)

Anyway, you need to enable alpha blending render state as well, in order to control the opacity of the drawn geometry with the alpha data.

Your texture stage state setup seems ok, but I recommend moving to pixel shaders as soon as possible to get more control and flexibility.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!