Sign in to follow this  

Alpha channel

This topic is 2066 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:
[CODE]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[/CODE]
but this sample doesn't work...

Share this post


Link to post
Share on other sites
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[/color] 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
[CODE]

int yGrad, xGrad;
D3DLOCKED_RECT lockedRect;

if(SUCCEEDED(LOCATIONS[b].g_pMeshTextures[i]->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[b].g_pMeshTextures[i]->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);
[/CODE]

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
[img]http://public.gamedev.net//public/style_emoticons/default/blink.png[/img] 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
[url="http://msdn.microsoft.com/en-us/library/windows/desktop/bb206357(v=vs.85).aspx"]http://msdn.microsof...7(v=vs.85).aspx[/url]
[url="http://msdn.microsoft.com/en-us/library/windows/desktop/bb172231(v=vs.85).aspx"]http://msdn.microsoft.com/en-us/library/windows/desktop/bb172231(v=vs.85).aspx[/url]

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
[CODE]

g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
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);
D3DLOCKED_RECT lr;

if(SUCCEEDED(LOCATIONS[b].g_pMeshTextures[i]->LockRect(0, &lr, NULL, D3DLOCK_DISCARD )))
{
for (UINT y = 0; y < 640; y++)
for (UINT x = 0; x < 640; x++)
{
unsigned char* pBytes = (unsigned char*)lr.pBits; // lr = D3DLOCKED_RECT you get from locking the texture
UINT offset = y * lr.Pitch + x * 4; // as explained in earlier post
pBytes[offset] = 0; // alpha, red, green, blue are unsigned chars 0...255
pBytes[offset + 1] = 0;
pBytes[offset + 2] = 0;
pBytes[offset + 3] = 255;
}
}
LOCATIONS[b].g_pMeshTextures[i]->UnlockRect((UINT)&lr);
// ????????????? ????????




LOCATIONS[b].g_pMesh->DrawSubset( i );
[/CODE]
if i setup all correctly - why i have black rectangles?

[quote name='Nik02' timestamp='1334130406' post='4930165']
, but I recommend moving to pixel shaders as soon as possible to get more control
[/quote]

maybe i'll try it if my current variant wont work...

Share this post


Link to post
Share on other sites
Also, a couple of points:

-Are you sure that the actual texture dimensions are 640x640? It is best to get the actual figures from the texture description structure (GetDesc(...)).
-If your texture has static content, don't lock it every frame - you only need to fill it once after creation.

Share this post


Link to post
Share on other sites
[quote name='Nik02' timestamp='1334175079' post='4930355']
-Are you sure that the actual texture dimensions are 640x640? It is best to get the actual figures from the texture description structure (GetDesc(...)).
[/quote]

so i i'll know their real size - i'll got one big black rectangle.....

[quote name='Nik02' timestamp='1334175079' post='4930355']
-If your texture has static content, don't lock it every frame - you only need to fill it once after creation.
[/quote]
i don't know why but i have asses violation when trying to lock it after creation...

P.S. you sad something about PS to create alpha channel, you know where i can read about it? i found this:
[CODE]

PS_OUTPUT ps_TransparentGrayscale(VS_OUTPUT In)
{
PS_OUTPUT Out;
{
float4 currentColor = tex2D(baseSampler, In.TextureCoords);
float4 finalColor = (currentColor.r + currentColor.g + currentColor.b) / 3;
finalColor.a = 127;
Out.Color = finalColor;
}
return Out;
}
[/CODE]
but what i need to and in my input\output struct in this sample?

Share this post


Link to post
Share on other sites
i've done it....here is my working code:
[CODE]g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);

g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);

g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2,D3DTA_CURRENT);[/CODE]
thx for help[img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

Share this post


Link to post
Share on other sites
also there is one problem....if i need 1 texture for checking alpha channel and one color texture, how can i setup alpha only for alpha texture? And from other texture i need to take just colors?

Share this post


Link to post
Share on other sites
Pixel shaders would make that very easy; however, it can also be realized by a purpose-built combination of texture stage states.

In TSS, each stage separates alpha and color, so you can cascade your alpha values from a previous stage and sample your color from the current stage (or vice versa).

Share this post


Link to post
Share on other sites
hm...nice but...how? if for example i loaded texture from file and save it to TEXTURE1, then in render states i need to set mesh[i] texture before drawing and turn off alpha channel, so where i shoud setup alpha for TEXTURE1, and let directX know that exactly this texture must be used for alpha?

P.S. You don't know where i can read about this? Cause in directX without code examples - its impossible to write code....

Share this post


Link to post
Share on other sites
Well, like I said - this would be very easy in pixel shaders:

[code]
struct PS_IN
{
float4 pos : POSITION;
float2 tc : TEXCOORD0;
}
Texture2D colortex; // this is the color texture
Texture2D alphatex; // this is the alpha texture
// set these from the host program

sampler ColorSampler = sampler2D
{
Texture = colortex;
// filters & stuff here as needed...
}
sampler AlphaSampler = sampler2D
{
Texture = alphatex;
// filters & stuff here as needed...
}
float4 PS (PS_IN input) : COLOR
{
// note that this is a very simple shader that does not do lighting of any kind
// simply fetch the color and alpha from separate textures:
float3 color = tex2d(ColorSampler, input.tc).rgb;
float alpha = tex2d(AlphaSampler, input.tc).a;
// then combine them to form the return value:
return float4(color, alpha);
}
[/code]

Share this post


Link to post
Share on other sites
In fixed function pipeline, you have a stack of texture stage states instead.

If you want to take color from texture bound in one stage, and alpha from other stage, here's the concept:

In stage 0:
-Set color texture to this stage.
-Setup color texture stage state in ordinary fashion.
In stage 1:
-Set texture containing alpha to this stage.
-Setup color arg 0 to be D3DTA_CURRENT, and color source to arg 0. This takes color values from previous stage (0).
-Setup alpha arg 0 to be D3DTA_TEXTURE, and alpha source to arg 0. This takes alpha values from the current stage (1).

Share this post


Link to post
Share on other sites
As for the documentation - the SDK docs have a programming guide that explains this stuff (at least the basics). The focus in the docs has long been towards shaders, though.

The fixed function stuff is considered legacy now, as the newer programming interfaces (D3D10 and up) do not even offer the fixed pipeline (in the same breadth as the old hardware does). Therefore, the documentation on FFP is becoming scarcer and more rare.

If you have specific questions, we can try to answer them here. I, for example, still remember a lot of the legacy FFP techniques even though I have moved to shaders a long time ago.

Share this post


Link to post
Share on other sites
I also remember that an old SDK (maybe D3D7 or D3D8) had a tool that let the user experiment with the texture stage state setup visually. You could try to hunt that down.

Or you could experiment with the setup in your own code; that's how I remember learning about this. If you use the reference device, there is very little chance of you crashing your machine upon eventual access violations ;)

Share this post


Link to post
Share on other sites
so i set texture:
[CODE]

g_pConstantTablePS->SetValue(g_pd3dDevice,"colortex",LOCATIONS[b].g_pMeshTextures[i],sizeof(LOCATIONS[b].g_pMeshTextures[i]));
g_pConstantTablePS->SetValue(g_pd3dDevice,"alphatex",LOCATIONS[b].g_pMeshTextures[i],sizeof(LOCATIONS[b].g_pMeshTextures[i]));
g_pd3dDevice->SetPixelShader( g_pPixelShader );
[/CODE]
replace my shader with yours and got 1 error:
" unexpected token Texture2D"...[img]http://public.gamedev.net//public/style_emoticons/default/mellow.png[/img]

Share this post


Link to post
Share on other sites
Add a semicolon to close the struct block. I didn't compile the code, it may contain other syntax errors.

If I remember correctly, texture handles are not assigned in D3D9 by using the constant table. Again IIRC, you can ask for a sampler index given a constant handle to the sampler defined in the shader, and then proceed to call SetTexture with that index in order to make the texture available to the shader.

Also, I thought your goal was to get color and alpha from different textures? That code would use the same texture object if it worked.

If your actual intent is to load rgba from the same texture, you don't have to do any extra combining at all in PS. The tex2d function returns the full rgba vector if you don't mask it.

Share this post


Link to post
Share on other sites

This topic is 2066 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.

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