Skip to main content

インクジオメトリパイプラインとレンダリング

一般的に、エンジンはラスターパーティクル(通称ラスターインク)とベクトルポリゴンレンダリング(通称ベクトルインク)を区別しており、その主な違いは下の表に示されています。 Ink Geometry Pipelineによって計算される幾何プリミティブは、Catmull-Rom スプラインを使用して補間される制御点を含むパスです。 これらの制御点に加え、ストロークの数学的モデルにより、各ストロークの開始および終了する最初と最後のセグメントに補間パラメータの値が指定されます。 すべてのパスは、必要に応じて変更可能な幅と不透明度で作成することができます。 ラスタライザーモジュールに採用されているラスタライズ技術は、これらの特徴を備えるパスを描くための技術です。

ラスターインクベクトルインク
ラスター レンダリングベクトル レンダリング
固定解像度 – グラフィックスをピクセルレベルで定義拡大縮小や移植が可能 – さまざまなデバイスでの印刷や表示に最適
ピクセルレベルでの加工、ぼかしなどが可能オブジェクトモデル – さまざまなジオメトリ操作による加工が可能
柔軟性が向上レンダリングが複雑化し、表現面での制約が増大

ベクトルインク(図形の塗りつぶし技術)は、可変幅のストロークをラスター化するための単色技術です。 この手法は、表現力の面での制約が大きくなりますが、より複雑なレンダリング技術と比較してパフォーマンスが優れているため、 通常の倍率変更が可能なベクトルグラフィックス向けや手書きアプリケーション向けに適しています。 表現がシンプルであるため、この技術でラスター化されたストロークは、分割、倍率変更、再描画などを容易に行うことができます(図1を参照)。

ベクトルレンダリングの例 図1:ベクトルの例

パーティクルインクは、パーティクルの重なりを使用してストロークをレンダリングします。 この技術を使用すると、レンダリングセクションに記載されている複数のレンダリングパラメータの制御により、より表現豊かなツール(クレヨン、鉛筆、水彩用ブラシなど)を作成できます。 これは、図2に示すような準専門的な作画用途に適しています。

ラスターレンダリングの例 図2:ラスターの例

パイプライン

コンピュータグラフィックスにおいて、レンダリングパイプラインとは、グラフィックスシステムがオブジェクトのレンダリングを実行する場合に必要なステップを記述する概念モデルです。WILLのインクレンダリングでは、このプロセスがすべてのプラットフォームで同様に採用されているジオメトリパイプラインと、プラットフォーム固有のグラフィックスフレームワークを利用するレンダリング部分に分割されています。

アプリケーションでは、geometry pipelineがInkBuilderで作成および設定されます。VectorInkBuilderがベクトルブラシのパイプラインを拡張するのに対し、RasterInkBuilderはラスター(パーティクル)ブラシに特化しています。WILL 3.0 @@@では、一連の処理ブロック*(プロセッサ、プロデューサなど)で構成されるgeometry pipelineを使用します。パイプラインの入力はポインタデータ(タッチ、スタイラス、マウス、またはコントローラ)*であり、これが一連の処理ステージを通過します。後続のステージが、各ステージの出力を入力として取得します。パイプラインの第一の目的はデジタルインクの作成です。ただし、汎用的に実装されているため、より幅広い機能を実現できます。

WILL 3のレンダリングパイプライン

図3:WILL 3のレンダリングパイプライン.

入力

最良の入力元はペンです。ペンは最大量のセンサ入力を提供し、書き込みやスケッチの際に最も自然な手段であるからです。

インクセンサーチャネルの概要

図4:インクセンサーチャンネルの概要

関連する入力は次のとおりです。

  • Position - xとyの座標で定義 - 入力点の位置
  • Phase - 入力の段階*(開始、アップデート/移動、終了)*
  • Timestamp - 入力のタイムスタンプ、速度の計算に使用
  • Force - オプション - (筆圧)筆圧を感知するスタイラス/ディスプレイによって通知される値
  • Radius - オプション - タッチ入力の太さ
  • Altitude Angle - オプション - 入力デバイスと書き込み面が成す仰角(OE)。0~π/2のラジアンで計測。
  • Azimuth Angle - オプション - オブジェクトの場所までの書き込み面に沿った角距離

慣例により、方位角(OA)は書き込み面に沿って上から下(北から南)へ計測されます。 0~2πのラジアンで計測(図5を参照)。

方位角図 図5:方位角を示した図

内部表現とモデル

  • ポインタデータ - (入力データ/タッチデータ) - 上記形式での入力

  • PathPoint - 点の内部表現

  • Path - PathPointの平面上の集合(図6を参照)であり、それぞれの点は計算機が計算します。これはあらかじめ定義するか、外部から受け渡すことができます。

Path-Points 図6:パスポイント

  • Layout - それぞれのパスポイントの項目の記述子

  • Spline - 求心性のCatmull–Rom スプライン(図7を参照)、制御点によって定義されます。

Catmull-Rom スプライン 図7:Catmull-Rom スプライン.

  • Point Set - (点だけではない)特定の形式で満たされる領域を定義する点の集合。 この技術では、点集合ではなく殻で定義された単純なブラシを使用します。

Point-Set 図8:点集合

  • *Polygon - ポリゴンは凸包を使用して点集合から作成されます。 ポリゴンはCollection<DIPoint2>:

Polygon Points 図9:ポリゴンの点

データクラス:

  • DIPoint2 - xおよびy座標を有する2Dの点
  • DIPoint3 - x、y、およびz座標を有する3Dの点
  • DIPoint4 - x、y、z座標および幅を有する3Dの点
  • DIPointList2D - Collection<DIPoint2>
  • DIPolyline - Collection<DIPoint2>

処理ブロック

パイプラインは、一連の処理ブロック(プロセッサ、プロデューサなど)で構成されます。 次の図は処理ブロックを視覚化し、中間ステップの例を示したものです。 生データ 図10:パイプラインとその中間結果

BaseDataProcessor

単一の入力項目に基づいてデータを処理するパイプラインステージの抽象基本クラスDataProcessor

2つの抽象メソッドを定義します。

  • add(phase: Phase, addition: Input, prediction: Input): Pair<Output, Output> - パイプラインステージにストロークデータを入力して処理します。
  • reset() - プロセッサを初期状態にリセットします。

PathProducer

提供されたレイアウトに基づいて入力を内部的なパスの表現に変換します。

コンストラクタパラメータ(Configクラスにラッピング):

  • Layout
  • Calculator - 入力をパスポイントに変換する関数

追加パラメータ:

  • Addition - InputData - 処理したい入力
  • Prediction - InputData - 将来的な入力の予測

出力:

  • Addition - 集合としてのパス<Float>
  • Prediction - 集合としてのパス<Float>

Smoother

ダブル指数平滑法によってパススムーザーを作成します。 スムージングの結果が良くないと、結果が1ポイント遅延します。

コンストラクタパラメータ:

  • レイアウトのサイズ(入力を処理する際にstrideとして使用)

追加パラメータ:

  • Addition - 集合<Float> - TouchToPathProducerによって生成されるパス
  • Prediction - 集合<Float> - TouchToPathProducerによって生成される予測パス

出力:

  • Addition - 集合としてのパス<Float>
  • Prediction - 集合としてのパス<Float>

SplineProducer

Catmull-Rom スプライン.を生成するために、2つの制御点(パスの始点と終点)を追加します。

コンストラクタパラメータ:

  • レイアウトのサイズ(入力を処理する際にstrideとして使用)

追加パラメータ:

  • Addition - Collection<Float> - パス
  • Prediction - Collection<Float> - 予測パス

出力:

  • Addition - Collection<Float>としてのスプライン
  • Prediction - Collection<Float>としてのスプライン

SplineInterpolator

間隔パラメータに従った間隔で点を軌道に沿って追加することにより、スプラインを離散化します。

コンストラクタパラメータ:

  • Layout
  • Spacing - サイズの乗数(1未満の場合は分数)として連続する2つの間隔
  • Split Count - 分割の回数

追加パラメータ:

  • Addition - Collection<Float> - スプライン
  • Prediction - Collection<Float> - 予測スプライン

出力:

  • Addition - Collection<Float>としてのスプライン
  • Prediction - Collection<Float>としてのスプライン

BrushApplier

点をブラシポリゴンに置き換えることにより、スプラインを点集合に変換します。

コンストラクタパラメータ:

  • Layout
  • Brush Polygon - ブラシを定義するポリゴン

追加パラメータ:

  • Addition - Collection<Float> - スプライン
  • Prediction - Collection<Float> - 予測スプライン

出力:

  • Addition - Collection<DIPointList2D>
  • Prediction - Collection<DIPointList2D>

ConvexHullChainProducer

単調連鎖アルゴリズムを使用して、2つの連続する点集合のそれぞれの周りに凸包を作成します。

追加パラメータ:

  • Addition - Collection<DIPointList2D> - 点集合
  • Prediction - Collection<DIPointList2D> - 予測点集合

出力:

  • Addition - Collection<DIPolygon>
  • Prediction - Collection<DIPolygon>

PolygonMerger

和集合を使用してポリゴンをマージします。 各種プラットフォームでClipperライブラリとそのそれぞれのポートを使用します。

追加パラメータ:

  • Addition - Collection<DIPolygon> - ConvexHullChainProducerによって生成された集合ポリゴン
  • Prediction - Collection<DIPolygon> - ConvexHullChainProducerによって生成された予測集合ポリゴン

出力:

  • Addition - Collection<DIPolygon>
  • Prediction - Collection<DIPolygon>

PolygonSimplifier

ラインセグメントで構成された曲線(ポリゴン)を取得し、Ramer-Douglas-Peucker アルゴリズム.を使用して少ない点の類似曲線を探します。

コンストラクタパラメータ:

  • Epsilon- 単純化のレベルを判定するしきい値。値が大きくなるほど、少ないセグメントのポリゴンになります。

追加パラメータ:

  • Addition - Collection<DIPolygon> - 集合簡素化ポリゴン
  • Prediction - Collection<DIPolygon> - 予測集合簡素化ポリゴン

出力:

  • Addition - Collection<DIPolygon>
  • Prediction - Collection<DIPolygon>

レンダリング

パイプラインの結果のレンダリングは、次のようなパーティクルレンダリングプラットフォームグラフィックスエンジンに対して行われ、その際には各プラットフォームの特定の2DレンダリングAPIが使用されます。

  • DirectXはWindows 10 UWP / WPF実装で使用されます。
  • OpenGLはラスターレンダリングに、Android Canvas(2D API) はベクトルに対応します。
  • MetalはiOSでのラスターレンダリングに使用されるのに対し、ベクトルレンダリングには Core Graphics
  • WebGLは当社のWebテクノロジーに使用されます。

プラットフォーム固有のベクトルレンダリング

ほとんどの場合、ベジェ曲線はパスオブジェクトとして使用され、パイプラインによって生成されるポリゴンの頂点を結ぶことで容易に作成できます。 この結果が塗りつぶされたベジェ輪郭であり、パスを表します。

PathPoint Calculator

この計算機はPathProducerステージに受け渡すメソッドであり、ポインタイベントのデータをパスポイントに変換する方法を定義します。 サンプルアプリケーションには、VectorInkBuilderに1つ、RasterInkBuilderに2つ(1つはペン入力用、もう1つはマウス用)の、合計3つのパスポイント計算メソッドの例が用意されています。

Inkの構築

パイプラインを使用するには、インクパスの内容を指定するデータレイアウトを作成する必要があります。 ここでは、基本的な(つまり、パスポイントがXとYの座標や可変サイズを有する)レイアウトが設定されます。使用可能な属性は次のとおりです。

  • PathPoint.Property.X - X座標
  • PathPoint.Property.Y >- Y座標
  • PathPoint.Property.Z - Z座標
  • PathPoint.Property.RED - 赤のカラー値
  • PathPoint.Property.GREEN - 緑のカラー値
  • PathPoint.Property.BLUE - 青のカラー値
  • PathPoint.Property.ALPHA - アルファカラー値
  • PathPoint.Property.SIZE - パスポイントに関連するサイズ値
  • PathPoint.Property.ROTATION - パスポイントに関連する回転値
  • PathPoint.Property.SCALE_X - パスポイントに関連するX次元のスケール値
  • PathPoint.Property.SCALE_Y - パスポイントに関連するY次元のスケール値
  • PathPoint.Property.SCALE_Z - パスポイントに関連するZ次元のスケール値
  • PathPoint.Property.OFFSET_X - パスポイントに関連するX次元のオフセット値
  • PathPoint.Property.OFFSET_Y - パスポイントに関連するY次元のオフセット値
  • PathPoint.Property.OFFSET_Z - パスポイントに関連するZ次元のオフセット値
  • PathPoint.Property.D_X - 接線ベクトルXの値
  • PathPoint.Property.D_Y - 接線ベクトルYの値

インクをリアルタイムにビルドするには、ポインタ入力イベントOnPointerPressedOnPointerMovedOnPointerReleased `を操作してInkBuilderに入力を与える必要があります。 InkBuilderは、最初のパイプラインステージであるPathProducerにポインタ入力データを渡します。 2つのフレーム間では複数の入力点を受け取ることができるため、PathProducerの出力は蓄積されます。 サンプルアプリケーションは、PathSegmentヘルパークラスを使用してパス部分を蓄積します。 その後、蓄積したパスは残りのパイプラインステージを通過します。 各ステージの出力は、次のステージの入力になります。 それぞれのパイプでは、1対の同一タイプのオブジェクトが生成されます。 最初のオブジェクトは追加データであり、2番目は予測(または予備)データです。 追加データはそのストロークの固定要素になりますが、予測データは仮のものであり、現在のフレームのみに表示されることになります。

ベクトルインクの構築

パイプラインステージはVectorInkBuilderコンストラクタで作成され、処理はGetPolygonsメソッドで行われます。 パイプラインは1対のポリゴンを出力します。一方は新しいストロークチャンクに相当し、もう一方は現在のフレームのみに表示される必要のある予測ポリゴンに相当します。

ラスターインクの構築

パーティクルインクの処理パイプラインは、ステージが少なくなります。

  • PathProducer
  • Smoother
  • SplineProducer
  • SplineInterpolator

これらはRasterInkBuilderコンストラクタで作成され、GetPathメソッドで処理が行われます。

インクのレンダリング

インクジオメトリを生成したら、これをさまざまな手法で表示できます。 サンプルアプリケーションでは、レンダリングライブラリを使用してベクトルインクやパーティクルインクの効率的なリアルタイムレンダリングを実現しています。

詳細についてはこちらでご確認いただけます。