Skip to content
React Native Skia ガイドブック
Esc
navigateopen⌘Jpreview
On this page

しくみを知る — 宣言的UIから描画パイプラインへ

React Native Skiaのコンポーネントツリーが、どのようにしてSkiaのシーングラフを経てGPUの描画命令になるのかを図解します。

ReactコンポーネントツリーがSkiaのシーングラフを経てピクセルへ変換される3段階の流れ

宣言したコンポーネントはシーングラフに整理され、GPUが最終的なピクセルを描きます。

<Canvas>の中に<Circle><Rect>を並べて書くと、見た目としては通常のReact Nativeコンポーネントを書いているのと変わりません。ですが、その裏側で起きていることはViewTextとはまったく違います。

Skiaは自前のReactレンダラーを持っている

React Nativeは、Reactが組み立てた要素ツリーを実際のネイティブUIに変換するために、専用のレンダラー(Renderer)を持っています。React Native Skiaも同様に、@shopify/react-native-skia専用のレンダラーを内部に持っていて、<Canvas>配下のJSXはこのレンダラーによって処理されます。

つまり<Canvas>の外側(通常のViewText)はReact Nativeのレンダラーが、<Canvas>の内側はSkia専用のレンダラーが担当するという、二つのレンダラーが同居する構造になっています。この境界があるため、<Canvas>の外で作ったReact Contextは、そのままでは内側から参照できません。両者は別のレンダラーツリーとして動いているためです。Contextをどうしても描画側に渡したい場合は、its-fineのようなライブラリでブリッジする必要があります(詳しくは公式のContextsを参照してください)。

描画までの3段階

<Canvas>に書いたコンポーネントツリーが画面に表示されるまでは、大まかに次の3段階を経ます。

1. Reactコンポーネントツリー

<Canvas>の中身は、他のReactコンポーネントとまったく同じ書き方をします。propsを渡し、useStateで状態を持ち、子コンポーネントに分割することもできます。この時点ではまだ「何を描くか」の宣言でしかなく、実際のピクセルは1つも計算されていません。

2. Skiaのシーングラフへの変換

Skia専用のレンダラーが、このコンポーネントツリーをSkiaのシーングラフ(内部的には描画命令の並んだリスト)に変換します。<Circle cx={128} cy={128} r={64} color="cyan" />は、最終的に「この座標にこの半径・色で円を描け」という命令に変換されます。<Group>でネストした場合は、その中の変換(transform)やブレンドモードもまとめて命令に反映されます。

3. GPUによるラスタライズ

組み立てられた描画命令は、Skiaのネイティブ実装(C++)からGPUに渡されます。iOSではMetal、AndroidではOpenGL(実験的にGraphite経由のVulkan)が実際のピクセル計算を担当し、その結果が画面に転送されます。React NativeのJavaScript側は、この最後の段階には直接関与しません。

worklet — UIスレッドで直接動くコード

アニメーションのように毎フレーム値を更新する処理を、JavaScriptスレッドとUIスレッドの間で毎回やり取りしていると、フレーム落ちの原因になります。そこでReact Native Skiaは、Reanimatedのworkletという仕組みと組み合わせて使えるようになっています。

workletは"worklet"という文字列を関数の先頭に書くだけの、ごく普通のJavaScript関数です。Reanimatedがこれを解析し、UIスレッド上でも実行できる形に変換します。

const radius = useSharedValue(64);

const transform = useDerivedValue(() => {
  "worklet";
  return [{ scale: 1 + Math.sin(radius.value) * 0.1 }];
});

このtransformをそのまま<Circle>transformpropに渡すと、UIスレッド上で計算された値がJavaScriptスレッドを介さずに直接Skiaの描画命令へ反映されます。図の2段階目(シーングラフへの変換)がUIスレッド上で完結するイメージです。workletとReanimatedの詳しい組み合わせ方は、第5部で改めて扱います。

まとめ

<Canvas>の中身は、Reactの見慣れた書き方のまま、Skia専用のレンダラーによってシーングラフに変換され、最終的にGPUで描かれます。この構造を頭に入れておくと、次の章で扱う「最初の描画」や「レンダリングモード」の違いも理解しやすくなります。