이 Post 에서는 WPF 상에서 HelixToolkit 과 HelixToolkit.SharpDX 의 성능을 비교해 보고, 월등한 성능의 SharpDX 를 사용하는 방법을 확인 합니다.
영상을 보시면 아시겠지만, HelixToolkit SharpDX 가 월등히 성능이 좋습니다.
레퍼런스가 더 많고, 접근성이 좋아 HelixToolkit 을 사용하는 경우가 훨씬 많지만 많은 3D 객체를 랜더링 하거나 실시간 상호작용이 필요한 경우에는 HelixToolkit SharpDX 를 사용하는 편이 좋습니다.
WPF, .NET Core 8.0 에서 테스트 했습니다.
0. 패키지


Nuget 에서 HelixToolkit.SharpDX.Core.Wpf 을 검색하여 설치 합니다.
.Net Framework 를 사용 하신다면 Core 가 붙지 않은 패키지를 설치 하시면 됩니다.
1. MainWIndow.xaml
<Window x:Class="HelixToolkitTest00_01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HelixToolkitTest00_01"
xmlns:hx="http://helix-toolkit.org/wpf/SharpDX"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<hx:Viewport3DX x:Name="viewPort"
Background="Black"
BackgroundColor="Black"
ShowCoordinateSystem="True"
ZoomAroundMouseDownPoint="True"
RotateAroundMouseDownPoint="True">
<hx:Viewport3DX.InputBindings>
<MouseBinding Command="hx:ViewportCommands.Rotate" Gesture="LeftClick"/>
<MouseBinding Command="hx:ViewportCommands.Pan" Gesture="RightClick"/>
</hx:Viewport3DX.InputBindings>
<hx:AmbientLight3D Color="#808080"/>
<hx:DirectionalLight3D Color="White" Direction="-1,-1,-1" />
</hx:Viewport3DX>
<TextBlock Text="Helix Toolkit SharpDX 1000 Sphere"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="0,10,0,0"
FontSize="40"
Foreground="White"/>
</Grid>
</Window>
7: HelixToolkit 의 namespace 를 지정 합니다.
11: Viewport3DX 추가
18~19: 마우스 왼쪽에 Rotate, 마우스 오른쪽에 Pan 을 연결 합니다. 이 설정을 안해주면 마우스 우측이 Rotate, 마우스 가운데 버튼을 누르면 Pan 으로 동작 합니다.
기본 설정이 좀 어색할 수 있지만, 사실 3D 객체를 클릭해서 어떤 액션을 취하거나 이벤트를 받기 위해서는 기본 설정이 더 낫습니다.
여기서는 딱히 3D 객체에 어떤 액션을 취할것이 아니기 때문에 익숙한 설정으로 변경 합니다.
21, 22: 기본 Light 를 설정 합니다. HelixToolkit 에서는 DefalutLight 로 퉁 쳤었지만 SharpDX 에서는 설정해 줘야 합니다.
2. MainWindow.xaml.cs – 초기화
using HelixToolkit.SharpDX.Core;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;
using System.Windows;
public MainWindow()
{
InitializeComponent();
viewPort.EffectsManager = new DefaultEffectsManager();
viewPort.Camera = new PerspectiveCamera
{
Position = new System.Windows.Media.Media3D.Point3D(100, 100, 100),
LookDirection = new System.Windows.Media.Media3D.Vector3D(-3, -3, -3),
UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 1, 0),
FarPlaneDistance = 500
};
this.Loaded += MainWindow_Loaded;
}
10: 랜더링 효과를 관리하는 매니저를 초기화 합니다.
11: 카메라를 설정 합니다.
3. MainWindow.xaml.cs – 구 그리기
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Random random = new Random(Guid.NewGuid().GetHashCode() + DateTime.Now.Millisecond);
for (int i = 0; i < 1000; i++)
{
CreateSphere(
random.Next(1, 100),
random.Next(1, 100),
random.Next(1, 100));
}
MessageBox.Show("구 생성 완료");
}
private void CreateSphere(float x, float y, float z, double radius = 1, int thetaDiv = 32, int phiDiv = 32)
{
var builder = new MeshBuilder();
builder.AddSphere(new Vector3(x, y, z), radius, thetaDiv, phiDiv);
var sphere = new MeshGeometryModel3D
{
Geometry = builder.ToMeshGeometry3D(),
Material = PhongMaterials.Red,
};
viewPort.Items.Add(sphere);
}
실제 구를 생성하는 부분입니다.
CreateSphere 에서 구를 생성하고 그걸 1000 회 반복 합니다.
구 하나는 위도 경도에 따라 기본적으로 32×32 개의 사각형을 가지게 됩니다.
사각형 하나는 두개의 폴리곤으로 구성이 되므로 2048 개의 폴리곤을 가지게 됩니다.
thetaDiv 나 phiDiv 를 줄이면 부하를 줄일 수 있지만 원의 모양은 점점 각이져 보이게 됩니다.
4. 사각형의 경우
private void CreateCube()
{
var builder = new MeshBuilder();
builder.AddBox(new Vector3(0, 0, 0), 1, 1, 1); // 중심(0,0,0)에, 각 변의 길이 1
var cube = new MeshGeometryModel3D
{
Geometry = builder.ToMeshGeometry3D(),
Material = DiffuseMaterials.Green,
};
viewPort.Items.Add(cube);
}
사각형 또한 다음과 같이 간단히 생성 할 수 있습니다.
기존에 개인적으로 실시간 3D 산점도 차트를 HelixToolkit 으로 만들려다가 부하 때문에 실패 했었습니다.
다른 라이브러리를 알아보다가 HelixToolkit.SharpDX 를 확인하게 되었는데, 상당히 만족스럽습니다.