Search code examples
c#wpfgraphics3dtransparency

WPF semi-transparent mesh issue


I have a mesh of truncated pyramids stacked on top of each other.

enter image description here

My goal is to reverse it, turning it into a sphere approximation. For that I draw the exact same thing, but Z-axis reversed. It works, except that the back is somehow semi transparent.

enter image description here

Here I set brush.Opacity = .3; to make the semi transparency problem more apparent.

enter image description here enter image description here

Unfortunately all I can find on the topic is failing to enable the transparency for separate mesh elements, not to remove it. What could be causing the problem, and how do I fix it? Here is the excerpt of my code in which I draw the mesh:

public void Approximate()
{
    group.Children.Clear();
    SolidColorBrush brush = new SolidColorBrush(Colors.Blue);
    DiffuseMaterial material = new DiffuseMaterial(brush);

    [...]

    for(int level = 0; level < level_number; level++)
    {
    GeometryModel3D model_front = new GeometryModel3D();
    model_front.Material = material;

    GeometryModel3D model_back = new GeometryModel3D();
    model_back.Material = material;

    [...]

    TruncatedPyramid pyramid1 = new TruncatedPyramid(bottom_points, top_points);
    pyramid1.Draw(model_front);
    group.Children.Add(model_front);

    TruncatedPyramid pyramid2 = new TruncatedPyramid(bottom_points, reverse_points);
    pyramid2.Draw(model_back);
    group.Children.Add(model_back);
    }
}

And in which I set up the window:

    <Viewport3D Name="myViewport" Margin="0,94,0,0" >

        <Viewport3D.Camera>
            <PerspectiveCamera  Position="10,10,10" LookDirection="-2,-2,-2" UpDirection="0,1,0" />
        </Viewport3D.Camera>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <DirectionalLight x:Name = "dirLightMain" Direction = "-1,-1,-1">
                </DirectionalLight>
            </ModelVisual3D.Content>
        </ModelVisual3D>

        <ModelVisual3D x:Name = "Wedge">
            <ModelVisual3D.Content>
                <Model3DGroup x:Name="group">

                </Model3DGroup>
            </ModelVisual3D.Content>

            <ModelVisual3D.Transform>
            [...]
            </ModelVisual3D.Transform>

        </ModelVisual3D>
    </Viewport3D>

The code that I removed definitely works fine and seems irrelevant to the problem (functions that calculate the points of the mesh and classes responsible for rotating the group)

My guess is that the front has some kind of transparency-related quality that the back still doesn't despite being drawn with the same brush, but I'm not familiar with WPF enough to find it.


Solution

  • I do not use WPF nor C# so can't help you with actual implementation. Anyway first see:

    I think your issue is wrong order of your triangles rendering. As you got more intersecting layers is this not easy to do in order independent way like in the link above. However there are more options how to deal with this:

    1. Z-Sorting

      you simply collect list of all triangles to render and sort them by distance to camera. As your mesh is self-intersecting you need to divide all intersected faces into non intersecting ones which is nasty thing to do and wery hard to implement properly. When done render the triangles in order back to front ...

    2. (Back) ray-tracing

      change your ender to ray tracing technique. These natively handle transparency correctly. Here an example:

    3. repair mesh

      You can use computation geometry to remedy your mesh by removing all interior faces from the mesh. But it is not easy for self intersecting meshes. When done then you can use the approach in the first link.

    I would go for #2 for complicated meshes but if you need speed then #3 is the way.