Alpha Blending... Again!

Started by
11 comments, last by Synex 19 years, 7 months ago
Ok... bit of a tricksy problem here. I've got a whole load of textured quads flying around which is all cool and nice and what not. And I have them alpha blended (using an alpha channel from a DDS). However, all of the alpha blending i've done so far has been against straight lines. When I came to do something a bit more complex it hit the fan. That is my problem. Image 1 shows the output I see on screen. Image 2 is the DDS file viewed in Adobe Photoshop. Image 3 is the result of me selecting the alpha channel and copying it onto another image with Photoshop. This is the same result I get when I used the Sprite helper class. It works fine, but using my own rendering code with a VertexBuffer it doesn't blend properly.

// setup vertex stream
			d_3DDevice.SetStreamSource(0, d_buffer, 0);

			// alpha blending 
			d_3DDevice.RenderState.AlphaTestEnable = true; 
			d_3DDevice.RenderState.ReferenceAlpha = 0x02; 
			d_3DDevice.RenderState.AlphaFunction = Compare.GreaterEqual; 

			d_3DDevice.RenderState.AlphaBlendEnable = true; 
			d_3DDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha; 
			d_3DDevice.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha; 

			d_3DDevice.TextureState[0].ColorOperation = TextureOperation.Modulate; 
			d_3DDevice.TextureState[0].ColorArgument1 = TextureArgument.TextureColor; 
			d_3DDevice.TextureState[0].ColorArgument2 = TextureArgument.Current; 

			d_3DDevice.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
			d_3DDevice.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; 
			d_3DDevice.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse; 
			
			d_3DDevice.RenderState.ZBufferEnable = true;
			d_3DDevice.RenderState.ZBufferFunction = Compare.Less;
			
			d_3DDevice.SetTexture(0, d_texture);

			// render the sprites
			d_3DDevice.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
			d_3DDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (d_bufferPos / VERTEX_PER_TRIANGLE));







That is the texture stages and what not I'm using. Any ideas where I am going wrong? Cheers, Tech Dude Code Monkey
SynexCode Monkey
Advertisement
Can you show an screen output? Can you send your vertex declaration? Are you using TLVertices? Are you filling your vertex color with an appropiate color? (white?) If you are using TLVertices, are you computing the w component by hand?

Luck!
Guimo


Image 1 is a screen output - I'll throw together a textured quad demo doodah tomorrow for you all to pull apart.
SynexCode Monkey
Use srcblend and destblend to affect color, rather than the new dx9 alphasrcblend and alphadestblend which allow a second alternate blending of alpha values.

1) What format is the texture inside your DDS file? - it looks like a format with only a 1-bit alpha channel. Try using a different format within the DDS.

2) Try disabling the alpha test.

[edit]
3) Aha, what Namethatnobodyelsetook said is actually most likely. I totally missed that (bedtime soon methinks).
[/edit]

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Ok here is a quick demo I threw togther:

using System;using System.Windows.Forms;using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;using System.Drawing;namespace TestConsole{	class CMain : System.Windows.Forms.Form	{		Device D3DDevice;		Sprite SpriteDevice;		Texture m_texture;		VertexBuffer m_buffer;		protected void InitGraphics()		{			PresentParameters pres = new PresentParameters (); 			pres.Windowed = true;			pres.SwapEffect = SwapEffect.Discard ; 			pres.BackBufferCount = 1;			pres.EnableAutoDepthStencil = true;			pres.AutoDepthStencilFormat = DepthFormat.D16;			D3DDevice = new Device(0, DeviceType.Hardware , this, CreateFlags.SoftwareVertexProcessing , pres);			SpriteDevice = new Sprite(D3DDevice);			m_texture = TextureLoader.FromFile(D3DDevice, "icons09.dds");			m_buffer = CreateVertexBuffer(D3DDevice);		}		protected VertexBuffer CreateVertexBuffer (Device device) 		{ 			CustomVertex.TransformedColoredTextured [] verts = 				new CustomVertex.TransformedColoredTextured [6]; 			verts [0] = 				new CustomVertex.TransformedColoredTextured ( 				0 + 64 + 256, 0, 0.1F, 0.1F, 				Color.White.ToArgb (),				0.0f, 0.0f); 			verts [1] = 				new CustomVertex.TransformedColoredTextured ( 				256 + 64 + 256, 0, 0.1F, 0.1F, 				Color.White.ToArgb (),				1.0f, 0.0f); 			verts [2] = 				new CustomVertex.TransformedColoredTextured ( 				0 + 64 + 256, 256, 0.1F, 0.1F, 				Color.White.ToArgb (),				0.0f, 1.0f); 			verts [3] = 				new CustomVertex.TransformedColoredTextured ( 				0 + 64 + 256, 256, 0.1F, 0.1F, 				Color.White.ToArgb (),				0.0f, 1.0f); 			verts [4] = 				new CustomVertex.TransformedColoredTextured ( 				256 + 64 + 256, 0, 0.1F, 0.1F, 				Color.White.ToArgb (),				1.0f, 0.0f); 			verts [5] = 				new CustomVertex.TransformedColoredTextured ( 				256 + 64 + 256, 256, 0.1F, 0.1F, 				Color.White.ToArgb (),				1.0f, 1.0f); 			VertexBuffer buf = 				new VertexBuffer ( 				typeof ( CustomVertex.TransformedColoredTextured ), 				verts.Length , 				device, 				0, 				CustomVertex.TransformedColoredTextured.Format , 				Pool.Default 				);			GraphicsStream stm = buf.Lock (0, 0, 0); 			stm.Write ( verts ); 			buf.Unlock (); 			return buf ;  		}		protected void RenderGraphics()		{			D3DDevice.VertexFormat = CustomVertex.TransformedColoredTextured.Format;			// alpha blending 			D3DDevice.RenderState.AlphaTestEnable = true; 			D3DDevice.RenderState.ReferenceAlpha = 0x01; 			D3DDevice.RenderState.AlphaFunction = Compare.GreaterEqual; 			D3DDevice.RenderState.AlphaBlendEnable = true; 			D3DDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha; 			D3DDevice.RenderState.AlphaDestinationBlend = Blend.InvSourceAlpha; 			D3DDevice.TextureState[0].ColorOperation = TextureOperation.Modulate; 			D3DDevice.TextureState[0].ColorArgument1 = TextureArgument.TextureColor; 			D3DDevice.TextureState[0].ColorArgument2 = TextureArgument.Diffuse; 			D3DDevice.TextureState[0].AlphaOperation = TextureOperation.Modulate; 			D3DDevice.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; 			D3DDevice.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse; 			D3DDevice.RenderState.ZBufferEnable = true;			D3DDevice.RenderState.ZBufferFunction = Compare.LessEqual;							D3DDevice.BeginScene();			D3DDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.BlueViolet, 1.0f, 0);			D3DDevice.SetTexture(0, m_texture);			D3DDevice.SetStreamSource(0, m_buffer, 0);			D3DDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);						SpriteDevice.Begin();			SpriteDevice.Draw(m_texture, new Rectangle(0, 0, 256, 256), new Vector2(1.0f, 1.0f), new Vector2(0.0f, 0.0f), 0.0f, new Vector2(0.0f, 0.0f), Color.White); 			SpriteDevice.End();			D3DDevice.EndScene();			D3DDevice.Present();		}		// Program Entrypoint		static void Main()		{			CMain app = new CMain();						app.Width = 800;			app.Height = 600;			app.InitGraphics();			app.Text = "Managed DirectX Test Sample";			app.Show();			while(app.Created)			{				app.RenderGraphics();				Application.DoEvents();			};		}	}}
SynexCode Monkey
Quote:Original post by Namethatnobodyelsetook
Use srcblend and destblend to affect color, rather than the new dx9 alphasrcblend and alphadestblend which allow a second alternate blending of alpha values.


Genius! - Worked first time!

Cheers bub I've been whacking my head against a wall all evening trying to figure this out!

SynexCode Monkey
Ok... so after getting that fixed, I'm now trying to make the quad translucent to a value I set when rendering the quad, say... 50% - How would I go about doing this?
SynexCode Monkey
I suggested a way to do translucency using the vertex diffuse component in this thread. And then at the very bottom, Supernat02 suggested an even easier way. Hopefully either one of them will help.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
If you're using vertex colors, set the alpha part of the vertex color to the percentage you'd like (255 = 100%, 128 = 50%, etc).

If you're using lighting, you can use Diffuse.a = 0.5f.

If you're not using lighting or vertex colors, you could use D3DRS_TEXTUREFACTOR. If are using vertex colors, but don't want to change them all the time (ie: for a real model), TFACTOR comes in handy, and you can use texture*diffuse*tfactor to blend all three alphas.

In your texture stage states, do something like this:

// mix texture with vertex color or lighting
pDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
pDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);

// Mix texture alpha with vertex or material.diffuse alpha
pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);

// Terminate at stage 1
pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

If you're going the TEXTUREFACTOR route, change the AlphaArg1 in stage 0, from D3DTA_DIFFUSE to D3DTA_TFACTOR.

This topic is closed to new replies.

Advertisement