Managed DirectX Alpha Blending did not work

Started by
3 comments, last by KDSBest 18 years, 4 months ago
Like the Title said, why is the alpha blending not working. dev init

			this.FormBorderstyle = FormBorderstyle.None;
			
			PresentParameters pparams = new PresentParameters();
			pparams.Windowed = true;
			this.Width = 800; this.Height = 600;
			pparams.BackBufferCount = 1;
			pparams.BackBufferFormat = Format.A8R8G8B8;
			pparams.BackBufferHeight = this.Height;
			pparams.BackBufferWidth = this.Width;
			pparams.AutoDepthStencilFormat = DepthFormat.D24S8;
            pparams.EnableAutoDepthStencil = true;
			pparams.SwapEffect = SwapEffect.Discard;

			dev = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pparams);
			
			dev.Transform.World = Matrix.Identity;
			dev.Transform.View = Matrix.LookAtLH(new Vector3(0,0,-30), new Vector3(0,0,0), new Vector3(0,1,0));
			dev.Transform.Projection = Matrix.PerspectiveFovLH((float) Math.PI / 4, this.Width/this.Height, 1.0f, 100.0f);
			
			dev.RenderState.Lighting = false;
			dev.RenderState.CullMode = Cull.None;

draw

			CustomVertex.PositionColored[] verts1 = new CustomVertex.PositionColored[3];
			CustomVertex.PositionColored[] verts2 = new CustomVertex.PositionColored[3];
			verts1[0].Position = new Vector3(0, 10, 0);
			verts1[1].Position = new Vector3(-10, 0, 0);
			verts1[2].Position = new Vector3(10, 0, 0);
			verts2[0].Position = new Vector3(5, 10, 2);
			verts2[1].Position = new Vector3(-5, 0, 2);
			verts2[2].Position = new Vector3(15, 0, 2);
			verts1[0].Color = verts1[1].Color = verts1[2].Color = Color.FromArgb(127, 255, 255, 255).ToArgb();
			verts2[0].Color = verts2[1].Color = verts2[2].Color = Color.FromArgb(127, 255, 0, 0).ToArgb();
			
			dev.RenderState.AlphaBlendEnable = true;
			dev.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
			dev.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha;
			
			dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
			dev.BeginScene();
			{
				dev.VertexFormat = CustomVertex.PositionColored.Format;
				dev.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts1);
				dev.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts2);
			}
			dev.EndScene();
			dev.Present();

[Edited by - Muhammad Haggag on December 1, 2005 4:40:25 AM]
Advertisement
Try SourceBlend and DestBlend rather than AlphaSourceBlend and AlphaDestBlend. The "Alpha" versions are for use when using seperatealphablendenable, blending the final alpha differently than blending the final color.
If i use the non "alpha" versions, the result is not the result i want to have. the triangle gets darker but i can't see the overlap.
You're likely seeing a blend with the background. When drawing alpha blended objects you *must* draw them back to front, except when using modulate or additive type blending.

You can disable ZWrites when drawing an object, allowing you to draw the front-most object first, then the more distant object, but the color mix will be incorrect, except in the case of add or modulate blending. The more layers of overlapping alpha objects, the worse the problem will be.

In general, draw all solid objects first. Next draw all alpha tested (on/off transparency, no blending) objects. Finally draw all alphablended objects sorted back to front, and likely with ZWrites disabled.

Technically you can draw the alpha tested objects whenever you want, but alphatest disables certain Z optimizations of modern GPUs and should be done after pure solid objects. While you can draw all these objects in any order, a rough front to back sort is best as a large nearby object will cause quick Z rejection of the further objects. These are all optimizations, and you can worry about them at a later time, but the Z sort of back to front for alpha blended objects isn't an optimization, it's the only way to have the math work properly.

As an example, lets clear to red, draw a green 50% square at depth 1, and a blue 50% square at depth 2. We'll do this 4 ways. With ZWrites on and off, and with green first then blue first.

Operation   Framebuffer Z=On   Framebuffer Z=OffClear       255, 000, 000      255, 000, 000Draw Green  128, 128, 000      128, 128, 000Draw Blue   128, 128, 000      064, 064, 128Clear       255, 000, 000      255, 000, 000Draw Blue   128, 000, 128      128, 000, 128Draw Green  064, 128, 064      064, 128, 064


The valid results are achieved when drawing blue then green, regardless of Z. The benefit of disabling Z writes is more for additive and modulate blending where depth ordering doesn't needed.

In the first case, with Z on and green first, we don't see the blue at all. It's hidden by the Z buffer holding the depth of the nearer green pixel first.

In the second case, with Z off and green first, we see a mix of all the colors, but it appears as though the blue is in front of the green, which isn't the case.
Looks great THX ZBufferWriteEnable = false, did excaktly what i wanted.

THX

This topic is closed to new replies.

Advertisement