Win2Dについて　その1　簡単な描画処理

# Win2Dの概要
C#の描画用ライブラリとしてWin2Dというものがあります。
これはDirectX(Direct2D)を使用して簡単に高性能なグラフィック表現をできるようにするためのライブラリになります。
以下の動画は古いものになりますが、Win2Dの特徴をうまく活用した動画になっています。
DirectXを使っているのでhlslなどのシェーダーによる表現やリアルタイムな表現が可能となっているのが大きな特徴なのではないでしょうか。
このWin2DはWinUI3で使えるようなので実際にこれを使って簡単なペイントアプリを作ってみたいと思います。
<iframe width="560" height="315" src="https://www.youtube.com/embed/VaxlXa809bQ?si=NfoEE-56kwCF6dGT" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# 準備
VisulaStudioでWinUI3のテンプレートを使用してプロジェクトを作成します。
Microsoft.Graphics.Win2DをNugetします。
![スクリーンショット 2024-11-30 220303.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949075/ce8f8734-5208-0f6b-dbbf-f43518e06711.png)

# コントロールの配置
Win2Dライブラリには描画用のコントロールがすでに作られているので、それをMainWindow.xamlに配置します。
```xml
<Window
    x:Class="Win2DPaint.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:Win2DPaint"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    >
    <Page Unloaded="control_Unloaded">
        <Grid Grid.Column="1" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <canvas:CanvasControl
                x:Name="canvas"
                Draw="Canvas_Draw"
                />
        </Grid>
    </Page>
</Window>
```
重要なのは以下の点です
1.Windowタグのxmlns:canvasにコントロール用のWin2Dライブラリを指定(名前は何でもいいです)
2.Gridの中に`<canvas:CanvasControl>`を追加。これがWin2Dの描画用コントロールになります。
3.`<canvas:CanvasControl>`にDrawイベントを追加し、`Canvas_Draw`関数を呼び出す。

この`Canvas_Draw`関数によって画面が描画される形になります。

# 描画処理
コントロールを配置したのでコードビヘイビアで描画処理を書いていきます。
```cs
private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
    args.DrawingSession.DrawEllipse(70, 50, 50, 25, Color.FromArgb(255, 0, 0, 0), 5);
    args.DrawingSession.FillEllipse(70, 50 + 50, 50, 25, Color.FromArgb(255, 255, 0, 0));
    args.DrawingSession.DrawCircle(70, 50 + 100, 25, Color.FromArgb(255, 0, 255, 0), 5);
    args.DrawingSession.FillCircle(70, 50 + 150, 25, Color.FromArgb(255, 0, 0, 255));
    args.DrawingSession.DrawRectangle(70, 50 + 200, 100, 50, Color.FromArgb(255, 255, 0, 255), 5);
    args.DrawingSession.FillRectangle(70, 50 + 250, 100, 50, Color.FromArgb(255, 0, 255, 255));
}
```

`Canvas_Draw`関数に`CanvasDrawEventArgs`が引数として与えられるので、この中の`DrawingSession`を取り出して各描画処理を呼び出しています。

![スクリーンショット 2024-11-30 223043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949075/e5bfef1f-6723-354a-94be-6c234263fb3a.png)
実行するとこのような形

各描画処理は基本的に第1、第2引数でコントロールの基準位置(左上)から位置(x,y)を表していて、第3、第4などで半径や幅、高さ、第5引数で色の情報、第6引数で線の太さを表しています。
例えば`DrawEllipse(70,50,50,25,Color.FromArgb(255,0,0,0),5)`だと、右上から右に70、下に50行った位置を基準に左右の半径を50、上下の半径を25とした黒の5ポイントの線で描かれた楕円を表しています。
`Fill～`系は塗りつぶしに線の太さは関係ないため、引数として存在しません。

このほかに位置をVector2として持たせるオーバーロードなどいろいろ用意しているため、以下のドキュメントを参考にしてください。
[Win2Dドキュメント(CanvasDrawingSession)](https://microsoft.github.io/Win2D/WinUI3/html/T_Microsoft_Graphics_Canvas_CanvasDrawingSession.htm)
Methodsの欄の`Draw～`や`Fill～`の関数が描画用の関数になります。

# 終わりに
Win2Dで簡単な描画処理をやってみました。
このほかにもペイントソフトのようにマウスドラッグで描画する方法やレイヤー処理についても以降の記事で書いていこうと思っています。