Sign in to follow this  

Alpha Blending... Again!

This topic is 4840 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

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

Share this post


Link to post
Share on other sites
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


Share this post


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

Share this post


Link to post
Share on other sites
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();
};


}
}
}

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by Agony
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.


Supernat suggested using FORCE_DWORD, WHICH ISN'T A SETTING, it's a dummy value on each enum to force them to require 32 bits. If he's using constant, he should set it to D3DTA_CONSTANT. Also, CONSTANT is a DX9 feature while TFACTOR is DX7, the advantage to CONSTANT being that you can put one per stage, instead of just one value overall.

To draw arbitrary full models transparently, disable color writes, draw with ZWrites enabled, enable color writes, draw again. Voila, the first pass forces the second pass not to produce overdraw.

Share this post


Link to post
Share on other sites
Ok... does anyone know how to set the Alpha component of a .NET Color structure? Or alternative how i would change the alpha component of the *int* that gets passed into the vertex buffer?

Share this post


Link to post
Share on other sites
Sorted it in a bit of a roundabout way -

SolidBrush trnsRedBrush = new SolidBrush(Color.FromArgb(120, 255, 0, 0));
int textureARGB = trnsRedBrush.Color.ToArgb();

Seems to work well! Toot toot!

Share this post


Link to post
Share on other sites

This topic is 4840 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