I can't find a way to use both my texture's alpha information, and also apply a alpha blend "on top" of that.
Texture alpha is no problem, I just use
SourceBlend = Blend.SourceAlpha;
DestinationBlend = Blend.InvSourceAlpha;
but I also want to "dim" the output arbitrarily.
First I was hoping that I could set the alpha value of the material's diffuse or ambient properties, or maybe use RenderState.BlendFactor, but that doesn't seem to be the way to go.
Now I'm trying a custom vertex with color:
X,Y;Z;Tu;Tv;Color;
using RenderState.ColorVertex = true
But it doesn't matter what I set the color to - only the texture's alpha is used.
It seems plausible that my customVertexFlags should be something else than VertexFormats.Position | VertexFormats.Texture1, but the other available flags seem out of place.
What's the best way to solve this TIA

Multiply alpha from texture and vertexcolor
Spy
In general, you should start a new thread for a new question. This thread is nearly 3 months old.
Alpha blending problems like you are having are common, and depending on how you're rendering, may be hard to fix. DirectX draws things in the order you ask. The Z buffer ensures that items with larger Z aren't drawn on the same pixels as something with a smaller Z. You plane at 0.5 is obsuring the character because, as far as D3D is concern, your plane at 0.5 is blocking it.
To use alpha blending effectively you should draw all solid objects first. If an object consists of multiple parts, some solid, some translucent, you should break it into two materials, and treat it as two completely seperate objects to render. So again, draw solids first, then draw all translucent objects from back to front.
Generally you can take the center of each object, transform it into viewspace, sort the resulting Z values and draw the objects in that order. This breaks down when two objects overlap. Various solutions exist (or don't exist) depending on the problem.
If you have items enclosing each other, such as layers of atmosphere, you can cull front faces, draw the objects from outer to inner, change the culling, and draw from inner to outer, effectively causing a Z sort.
If you have shapes, like leaves, of 2D sprites, and the alpha is generally on or off, use alphatest rather than alphablending. Any pixel failing the alphatest is not written to either the color or depth buffer.
Worst case (and no game tries this) you can sort by polygon depth. But what about when two polygons intersect You must split the polygons into pieces to sort correctly.
For you, make the two planes seperate objects. Draw the character and stove, then the far plane, followed by the near plane.
Dale Computer Help
Your colorkey doesn't look right, so the image likely doesn't actually have alpha in it. If you're using pure green (0,255,0) your color key should be 0xFF00FF00 (alpha=255, red=0, green=255, blue=0).
Perhaps if you posted your full code somewhere I could take a look at it.
Rok Yu
I really appreciate you taking the time...first off, the green image i posted earlier DID NOT have an alpha channel. i created a new one and verified that it does in fact have an alpha channel by opening it in the DirectX Texture Tool (the background shows through). Another thing I was unclear about that you just cleared up is that the alpha value needs to be the first byte of the colorkey (I was making it the last). But even changing both of these things, it still does not work. Now the entire middle plane is white. I feel as though I am so close. Sorry I couldn't post the entire project, but I went ahead and posted the relevant code below:
Note: The only non-default render states I have set in the ResetDevice is that I turned off lighting (e.Device.RenderState.Lighting = false)
// here is the code that sets up the middle plane
vb1 =
new VertexBuffer(typeof(CustomVertex.TransformedTextured), 4, _Device, 0, CustomVertex.TransformedTextured.Format, Pool.Managed);stm = vb1.Lock(0, 0, 0);
CustomVertex.TransformedTextured[] verts1 = new CustomVertex.TransformedTextured[4];
verts1[0].X = 0; verts1[0].Y = 0; verts1[0].Z = 0.9f; verts1[0].Rhw = 1; verts1[0].Tu = 0; verts1[0].Tv = 0;
verts1[1].X = 800; verts1[1].Y = 0; verts1[1].Z = 0.9f; verts1[1].Rhw = 1; verts1[1].Tu = 1; verts1[0].Tv = 0;
verts1[2].X = 0; verts1[2].Y = 600; verts1[2].Z = 0.9f; verts1[2].Rhw = 1; verts1[2].Tu = 0; verts1[2].Tv = 1;
verts1[3].X = 800; verts1[3].Y = 600; verts1[3].Z = 0.9f; verts1[3].Rhw = 1; verts1[3].Tu = 1; verts1[3].Tv = 1;
stm.Write(verts1);
vb1.Unlock();
// here is the code that sets up the texture for middle plane
string fname = Utility.FindMediaFile("kitchen_new.dds"); unchecked{
StoveTexture =
TextureLoader.FromFile(_Device, fname, 800, 600, 0, Usage.None, Format.A8R8G8B8, Pool.Managed, Filter.None, Filter.None, (int) 0xFF000000);}
// here is the render code
_Device.RenderState.AlphaBlendEnable =
true;_Device.RenderState.SourceBlend =
Blend.SourceAlpha;_Device.RenderState.DestinationBlend =
Blend.InvSourceAlpha;_Device.SetStreamSource(0, vb1, 0);
_Device.VertexFormat =
CustomVertex.TransformedTextured.Format;_Device.DrawPrimitives(
PrimitiveType.TriangleStrip, 0, 2);sneakyfeline
I hope this is the correct place to post this question, but I too and having difficulty understanding what type of blending I need to achieve the following results:
I have 2 TransformedTextured planes in my scene and 1 3D character (tiny.x). One of the planes acts as the "background of the scene" and sits at Z = 1.0.
There is a stove in our scene, and it sits about halfway between the front and back clipping planes (z = 0.5 post transformed). The character needs to appear as though she is walking behind the stove, so we created the 2nd TransformedTextured plane (same width and height as the first plane) and gave the entire texture for this plane an alpha value with the exception of the stove.
When the scene is rendered, the player is at z = 0.0, the 2 planes appear as though they are one, and all is well. But when you click to make the player walk to the back of the scene (to z = 1.0), she disappears when she gets behind the plane at z = 0.5. The result we are seeking is to have her continue to appear between z = 0.5 and 1.0 EXCEPT when she walks behind the stove. Can anyone give us insight into how we might achieve this result We seem to believe that a series of RenderState and/or TextureState flags will do the trick.
Thanks
JoeeT
Apologies to all...I really can't believe this. In all of my code kludging to get this stuff to work, my last code edit removed the SetTexture call if you can believe that. Since the alpha channel was added, the following code will work for alpha blending.
// setting up the texture. note that the extended params (color channel) are not needed
string fname = Utility.FindMediaFile("kitchen_new.dds");
StoveTexture =
TextureLoader.FromFile(_Device, fname);// here is the render code
_Device.SetTexture(0, StoveTexture);
_Device.RenderState.AlphaBlendEnable =
true;_Device.RenderState.SourceBlend =
Blend.SourceAlpha;_Device.RenderState.DestinationBlend =
Blend.InvSourceAlpha;_Device.SetStreamSource(0, vb1, 0);
_Device.VertexFormat =
CustomVertex.TransformedTextured.Format;_Device.DrawPrimitives(
PrimitiveType.TriangleStrip, 0, 2);KMJ
hth
Jack
arktseytlin
here's a screen shot:
http://i17.photobucket.com/albums/b95/julesthe/bad.jpg
you are seeing the middle plane and the green comes from the texture itself (png image) ..
obviously, i need for the green to "disappear" and show through to the background.
_Device.RenderState.AlphaBlendEnable = true; _Device.RenderState.SourceBlend = Blend.SourceAlpha; _Device.RenderState.DestinationBlend = Blend.InvSourceAlpha;The vertex buffer is a TransformedTextured quad and i use the following code to render:
_Device.SetTexture(0, StoveTexture);
_Device.SetStreamSource(0, vb1, 0);
_Device.VertexFormat =
CustomVertex.TransformedTextured.Format;_Device.DrawPrimitives(
PrimitiveType.TriangleStrip, 0, 2);australenia
Ah, so the stove is part of the image... Just draw the background and character first with no alpha blending. Next enable alpha blending and draw the plane with the stove. If the character is in front of the stove and translucent part it will not blend because of Z buffering. If the character is behind the stove, it will be occluded because the stove's alpha is 255... blending will still occur, but since the stove has full alpha, it will overwrite the character.
You likely want plain SourceBlend and DestBlend. AlphaSourceBlend and AlphaDestBlend are for when you have seperatealphablendenable (ie: blend color differently from alpha, useful if you have alpha in your backbuffer/render target).
Also, you modulate the alpha with the "current" alpha. Current on stage 0 means the same as diffuse. This is either your vertex alpha, or material diffuse alpha, if lighting is enabled and using material colors. If you are using this to dynamically reduce the alpha level, it will cause the stove to become partly transparent too, and not fully occlude the character.
Nicolai Klausen
Thanks - as noted, I got an answer (the same) on the DirectXDev list, and I tried to get back here to note the solution for reference. However, this site was unavailable or timing out each time I made an attempt...
If it was available as a proper mailing list (is it ) I'd use it a lot more than the 1-2 times a month I check it out ATM. The "alert me" function doesn't seem to work either.
Simfool
yea .. you got it. that's what I am doing. i just realized that i was loading the wrong texture for the middle plane .. duh!
I am now loading the correct texture , but it is still not quite working. here's some pseudo code:
disable alpha blending
draw background
draw character
enable alpha blending
RenderState.SourceBlend = Blend.SourceAlpha
RenderState.DestinationBlend = Blend.InvSourceAlpha
render middle plane
also, I am loading the texture with:
StoveTexture =
TextureLoader.FromFile(_Device, fname, 800, 600, 0, Usage.None, Format.Unknown, Pool.Managed, Filter.None, Filter.None, 0x0CFF0000);Pratik
You need to tell D3D what the final alpha is by setting up your TextureStageStates.
Assuming you want "texture * lighting" as your color, you'll want to do this:
pDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
You may need to set the light color alpha to 1.0 for your material diffuse alpha to pass through correctly.
If you can't get material diffuse working, you can use TFACTOR, like so:
pDev->SetRenderState(D3DRS_TEXTUREFACTOR, alpha<<24);
and change the alphaarg2 in stage 0 above from D3DTA_DIFFUSE to D3DTA_TFACTOR.
edit: Doesn't look like you're using C++, but you can likely translate this easily enough.
deeceethree
Thanks for the feedback.
I really think the solution to my problem is a simple one (even though I can't get it). Check this picture out:
Cheap Drawing
The squiggly line plane is the background, and the hatched line pattern plane is the plane at z = 0.5. Finally, there's the stickman character at z = 0.0.
Each time I render the scene, I:
1) Draw the background
2) Draw the character
3) Draw the plane at z = 0.5
The hatched plane has a texture applied with an alpha channel. The hatched portion is the transparent portion and as you can see there is a tiny portion (the stove) that should not be transparent.
I tried the following settings (and variations of these) just prior to rendering the middle plane:
_Device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
_Device.TextureState[0].ColorOperation = TextureOperation.Modulate;
_Device.TextureState[0].ColorArgument2 = TextureArgument.Current;
_Device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
_Device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
_Device.TextureState[0].AlphaArgument2 = TextureArgument.Current;
_Device.TextureState[1].ColorOperation = TextureOperation.Disable;
_Device.TextureState[1].AlphaOperation = TextureOperation.Disable;
_Device.RenderState.AlphaTestEnable = true;
_Device.RenderState.AlphaFunction = Compare.NotEqual;
_Device.RenderState.ReferenceAlpha = 0;
_Device.RenderState.AlphaBlendEnable = true;
_Device.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
_Device.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha;
_Device.RenderState.ZBufferEnable = true;
_Device.RenderState.ZBufferWriteEnable = true;
and none of the settings gave me the result I was looking for. Can anyone see from either the image or the code where I am going wrong
Note too that both planes are pre-transformed (TransformedTextured).