3

I created a full-screen WPF Canvas, representing a time line. Only the visible part of the time line is composed, so (practically) no UI elements lie outside of the visible range.

Time line 2D

I'm trying to add perspective to this time line using a Viewport3D. The result at the moment looks as follows:

Time line 3D

You can scroll the time line left and right by dragging. Performance in the 2D version is great. However, once the canvas is placed inside a Viewport3D using Viewport2DVisual3D, performance drops drastically.

It's not like I'm rendering a complex mesh, where is this performance decrease coming from, and can I prevent it?

To give you an idea of how the 3D perspective was realized I'll add the XAML code here, unfortunately it doesn't work on its own.

<Grid Background="{StaticResource BackgroundBrush}">
    <Viewport3D ClipToBounds="False">
        <Viewport3D.Camera>
            <PerspectiveCamera
                Position="0 0 5"
                LookDirection="0.4 0 -1"
                UpDirection="0 1 0" />
        </Viewport3D.Camera>

        <ContainerUIElement3D>
            <ModelUIElement3D>
                <AmbientLight Color="White" />
            </ModelUIElement3D>
        </ContainerUIElement3D>

        <Viewport2DVisual3D>
            <Viewport2DVisual3D.Geometry>
                <MeshGeometry3D
                    TriangleIndices="0,1,2 2,3,0"
                    TextureCoordinates="0 0, 0 1, 1 1, 1 0">
                    <MeshGeometry3D.Positions>
                        <MultiBinding Converter="{StaticResource AspectRatioToPositions}">
                            <Binding ElementName="TimeLineContainer" Path="Width" />
                            <Binding ElementName="TimeLineContainer" Path="Height" />
                        </MultiBinding>
                    </MeshGeometry3D.Positions>
                </MeshGeometry3D>
            </Viewport2DVisual3D.Geometry>

            <Viewport2DVisual3D.Material>
                <DiffuseMaterial
                    Viewport2DVisual3D.IsVisualHostMaterial="True"
                    Brush="White" />
            </Viewport2DVisual3D.Material>

            <Grid 
                x:Name="TimeLineContainer"
                Width="1650" Height="600"
                ClipToBounds="True"
                Background="{StaticResource TimeLineBrush}"
                Behaviors:MouseBehavior.LeftClickDragCommand="ActivityOverview:ActivityOverviewWindow.MouseDragged"
                MouseWheel="OnMouseWheel"
                MouseMove="OnMouseMoved">

                <ActivityOverview:TimeLineControl x:Name="TimeLine" Focusable="True">
                    <ActivityOverview:TimeLineControl.CommandBindings>
                        <CommandBinding
                            Command="ActivityOverview:ActivityOverviewWindow.MouseDragged"                  
                            Executed="MoveTimeLine" />
                    </ActivityOverview:TimeLineControl.CommandBindings>
                </ActivityOverview:TimeLineControl>

            </Grid>
        </Viewport2DVisual3D>
    </Viewport3D>
</Grid>
Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161
  • There could be all sorts of reasons, if you don't have hardware acceleration on your graphics card being one. – ChrisF Mar 02 '12 at 10:55
  • @ChrisF: I have hardware acceleration, and the mesh is just two triangles. – Steven Jeuris Mar 02 '12 at 10:56
  • Can you post the minimum code that repeats the problem. Also when I was doing 3D (many years ago now) there were issues on some cards if you were using gradient fills - which I notice you are. Try removing that. If nothing else it will eliminate it as a possibility. – ChrisF Mar 02 '12 at 11:00
  • @ChrisF: Removing the gradients didn't make a difference. They worked fluently in the 2D version as well. I'm thinking of hit tests which might be more expensive in 3D now. – Steven Jeuris Mar 02 '12 at 11:10

2 Answers2

2

When using Viewport2DVisual3D performance can be slow when you attempt to display content that is time-consuming to render. This seemed to be the case in my example.

For this reason, you can set the CacheMode of Viewport2DVisual3D.

<Viewport2DVisual3D>
    <Viewport2DVisual3D.CacheMode>
        <BitmapCache />
    </Viewport2DVisual3D.CacheMode>        
    ...
</Viewport2DVisual3D>

Starting from Windows Vista, anti-aliasing is enabled by default. Disabling this also helps in improving performance. It's weird this would have a big impact with such a simple mesh (two triangles), but on my PC, it does!

<Viewport3D ClipToBounds="False" RenderOptions.EdgeMode="Aliased">

Combining these two settings, I got great improvements.

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161
0

Hi guys you can use <OrthographicCamera Position="0 0 5" LookDirection="0.4 0 -1" UpDirection="0 1 0" /> . Please check my code below

<Grid Background="{StaticResource BackgroundBrush}">
<Viewport3D ClipToBounds="False">
    <Viewport3D.Camera>
        <OrthographicCamera
            Position="0 0 5"
            LookDirection="0.4 0 -1"
            UpDirection="0 1 0" />
    </Viewport3D.Camera>

    <ContainerUIElement3D>
        <ModelUIElement3D>
            <AmbientLight Color="White" />
        </ModelUIElement3D>
    </ContainerUIElement3D>

    <Viewport2DVisual3D>
        <Viewport2DVisual3D.Geometry>
            <MeshGeometry3D
                TriangleIndices="0,1,2 2,3,0"
                TextureCoordinates="0 0, 0 1, 1 1, 1 0">
                <MeshGeometry3D.Positions>
                    <MultiBinding Converter="{StaticResource AspectRatioToPositions}">
                        <Binding ElementName="TimeLineContainer" Path="Width" />
                        <Binding ElementName="TimeLineContainer" Path="Height" />
                    </MultiBinding>
                </MeshGeometry3D.Positions>
            </MeshGeometry3D>
        </Viewport2DVisual3D.Geometry>

        <Viewport2DVisual3D.Material>
            <DiffuseMaterial
                Viewport2DVisual3D.IsVisualHostMaterial="True"
                Brush="White" />
        </Viewport2DVisual3D.Material>

        <Grid 
            x:Name="TimeLineContainer"
            Width="1650" Height="600"
            ClipToBounds="True"
            Background="{StaticResource TimeLineBrush}"
            Behaviors:MouseBehavior.LeftClickDragCommand="ActivityOverview:ActivityOverviewWindow.MouseDragged"
            MouseWheel="OnMouseWheel"
            MouseMove="OnMouseMoved">

            <ActivityOverview:TimeLineControl x:Name="TimeLine" Focusable="True">
                <ActivityOverview:TimeLineControl.CommandBindings>
                    <CommandBinding
                        Command="ActivityOverview:ActivityOverviewWindow.MouseDragged"                  
                        Executed="MoveTimeLine" />
                </ActivityOverview:TimeLineControl.CommandBindings>
            </ActivityOverview:TimeLineControl>

        </Grid>
    </Viewport2DVisual3D>
</Viewport3D>

KaluSinghRao
  • 95
  • 1
  • 11