Material alpha blending in managed DirectX

Started by
3 comments, last by ifaaan 15 years, 8 months ago
I have the following code:

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace TestProgram {
    class TestForm : Form {
        Mesh mesh1;
        Mesh mesh2;
        Device device;

        public TestForm() {
            PresentParameters present;
            present = new PresentParameters();
            present.Windowed = true;
            present.AutoDepthStencilFormat = DepthFormat.D16;
            present.EnableAutoDepthStencil = true;
            present.SwapEffect = SwapEffect.Discard;
            present.MultiSample = MultiSampleType.TwoSamples;
            present.BackBufferWidth = 1280;
            present.BackBufferHeight = 1024;
            present.BackBufferFormat = Format.R5G6B5;

            device = new Device(0, DeviceType.Hardware, this,
                                CreateFlags.HardwareVertexProcessing, present);
            device.DeviceReset += new EventHandler(OnDeviceReset);
            OnDeviceReset(null, EventArgs.Empty);


            mesh1 = Mesh.Box(device, 100.0f, 100.0f, 100.0f);
            mesh2 = Mesh.Box(device, 50.0f, 50.0f, 50.0f);
        }

        private void OnDeviceReset(object sender, EventArgs e) {

            device.Transform.Projection = Matrix.PerspectiveFovRH(
               (float)Math.PI / 4.0F,
               (float)this.ClientSize.Width / (float)this.ClientSize.Height,
               0.001f, 1000);

            device.Transform.View = Matrix.LookAtRH(new Vector3(90, 0, 300),
                new Vector3(0, 0, 0), new Vector3(0, 1, 0));

            device.RenderState.Lighting = true;


            device.Lights[0].Diffuse = Color.White;
            device.Lights[0].Specular = Color.White;
            device.Lights[0].Type = LightType.Directional;
            device.Lights[0].Direction = new Vector3(-19, -5, -40);
            device.Lights[0].Enabled = true;
            device.Lights[0].Attenuation0 = 1000.0f;
            device.RenderState.CullMode = Cull.None;
            device.RenderState.Ambient = System.Drawing.Color.White;
        }


        protected override void OnPaint(PaintEventArgs e) {
            Material material = new Material();


            device.BeginScene();
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
                        Color.White, 1.0f, 0);

            material.Ambient = Color.FromArgb(255, 0, 0, 255);
            material.Diffuse = Color.FromArgb(255, 0, 0, 255);
            material.Emissive = Color.FromArgb(255, 0, 0, 255);
            material.Specular = Color.FromArgb(255, 0, 0, 255);
            device.RenderState.AlphaBlendEnable = false;
            device.Material = material;
            mesh2.DrawSubset(0);

            material.Ambient = Color.FromArgb(30, 255, 0, 0);
            material.Diffuse = Color.FromArgb(30, 255, 0, 0);
            material.Emissive = Color.FromArgb(30, 255, 0, 0);
            material.Specular = Color.FromArgb(30, 255, 0, 0);
            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.DiffuseMaterialSource = ColorSource.Material;
            device.Material = material;
            mesh1.DrawSubset(0);

            device.EndScene();
            device.Present();
        }


        static void Main() {
            Application.Run(new TestForm());
        }
    }
}



It must draw transparent red cube and blue cube seen through it. But I have a following picture: Where I mistaken?
Advertisement
For one thing, you first draw a solid red cube. Once that's drawn, nothing inside that cube will be rendered.

It sounds like you should render the inside cube first, with alpha=1. Then render the red cube with alpha < 1.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Noup, first I draw blue cube, which is smaller when red cube and placed inside it.
After enabling alpha blending you must choose how to blend.

What you're doing is done via:
pDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
pDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

This says to multiply the new (src) pixels by the new alpha,
Multiply the old (dest) pixels by (1-new alpha)
Add the results

color = newcolor*newalpha + oldcolor*(1-newalpha);

You may also need to adjust the texture stages to use vertex/material alpha. I'll show using color without texture here)

pDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);

pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

This sets up a simple single stage which just takes the diffuse color and outputs to the blending stage.
2 Namethatnobodyelsetook:
Thanks. Now it's really works.

This topic is closed to new replies.

Advertisement