Question

I'm rendering several cubes created with geometry shader (I load only locations and color), each with different alpha value. The problem is, that after enabling of alpha blending, visibility of the cubes changes with angle I look at them. Objects with alpha >0.5 that seem pretty solid, practically dissapear when I rotate them a little.

The red cube has alpha = 255 and yet we can see whats below it. I've tried enabling and disabling stencil buffer but it doesn't make any change, so I guess it's either my shader or something simple like wrong flag value.

http://tinypic.com/r/10e589v/8

Alpha blending

            var depthDisabledStencilDesc = new DepthStencilStateDescription()
        {
            IsDepthEnabled = false,
            DepthWriteMask = DepthWriteMask.All,
            DepthComparison = Comparison.Less,
            IsStencilEnabled = true,
            StencilReadMask = 0xFF,
            StencilWriteMask = 0xFF,
            // Stencil operation if pixel front-facing.
            FrontFace = new DepthStencilOperationDescription()
            {
                FailOperation = StencilOperation.Keep,
                DepthFailOperation = StencilOperation.Increment,
                PassOperation = StencilOperation.Keep,
                Comparison = Comparison.Always
            },
            // Stencil operation if pixel is back-facing.
            BackFace = new DepthStencilOperationDescription()
            {
                FailOperation = StencilOperation.Keep,
                DepthFailOperation = StencilOperation.Decrement,
                PassOperation = StencilOperation.Keep,
                Comparison = Comparison.Always
            }
        };

        // Create the depth stencil state.
        DepthDisabledStencilState = new DepthStencilState(Device, depthDisabledStencilDesc);
        //turn z-buffer off
        Device.ImmediateContext.OutputMerger.SetDepthStencilState(DepthDisabledStencilState, 1);

        #region Initialize Blending
        BlendStateDescription blendDesc = new BlendStateDescription();

        blendDesc.RenderTarget[0].IsBlendEnabled = true;
        blendDesc.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
        blendDesc.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
        blendDesc.RenderTarget[0].BlendOperation = BlendOperation.Add;
        blendDesc.RenderTarget[0].SourceAlphaBlend = BlendOption.One;
        blendDesc.RenderTarget[0].DestinationAlphaBlend = BlendOption.InverseSourceAlpha;
        blendDesc.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
        blendDesc.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;

        AlphaEnableBlendingState = new BlendState(Device, blendDesc);

        // Setup the blend factor.
        var blendFactor = new Color4(0, 0, 0, 0);

        Device.ImmediateContext.OutputMerger.SetBlendState(AlphaEnableBlendingState, blendFactor, -1);

Geometry shader

    float4 v1 = input[0].Pos/2 + float4(-scale * cube_size, -scale * cube_size, -scale * cube_size, 0) + offset;
float4 v2 = input[0].Pos/2 + float4(-scale * cube_size, scale * cube_size, -scale * cube_size, 0) + offset;
float4 v3 = input[0].Pos/2 + float4(scale * cube_size, scale * cube_size, -scale * cube_size, 0) + offset;
float4 v4 = input[0].Pos/2 + float4(scale * cube_size, -scale * cube_size, -scale * cube_size, 0) + offset;

float4 v5 = input[0].Pos/2 + float4(-scale * cube_size, -scale * cube_size, scale * cube_size, 0) + offset;
float4 v6 = input[0].Pos/2 + float4(-scale * cube_size, scale * cube_size, scale * cube_size, 0) + offset;
float4 v7 = input[0].Pos/2 + float4(scale * cube_size, scale * cube_size, scale * cube_size, 0) + offset;
float4 v8 = input[0].Pos/2 + float4(scale * cube_size, -scale * cube_size, scale * cube_size, 0) + offset;

v1 = mul(v1, World);
v1 = mul(v1, View);
v1 = mul(v1, Projection);

v2 = mul(v2, World);
v2 = mul(v2, View);
v2 = mul(v2, Projection);

v3 = mul(v3, World);
v3 = mul(v3, View);
v3 = mul(v3, Projection);

//front
float4 edge1 = v3-v2;
float4 edge2 = v1-v3;
output.Normal = cross(edge1, edge2);

output.Pos = v3;    
OutputStream.Append(output);            
output.Pos = v2;
OutputStream.Append(output);            
output.Pos = v1;
OutputStream.Append(output);

output.Pos = v3;
OutputStream.Append(output);        
output.Pos = v4;
OutputStream.Append(output);        
output.Pos = v1;
OutputStream.Append(output);
OutputStream.RestartStrip();

Other faces are created in the same way.

Was it helpful?

Solution

To blend with a background primitive, that same background primitive has to be rendered first in order to performance desired blending operation with exiting pixel colors.

Blending Stage

If order is inverted, the second primitive will be occluded by the first one and you will end up only with the last primitive pixel color.

Hope it helps you get closer to your objective.

Cheers

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top