WindowCapture2D 今回UnrealEngineで使えるウィンドウキャプチャープラグインをGitHub上に公開しました。
今はGitHubでのみ公開していますが、もう少し機能がまとまり次第マーケットプレイスにも出そうと思っています。
WindowCaptureへの思い ある時にVRコンテンツをUE4でWindows上のアプリケーションをVR空間に表示したくて色々調べてたのですが、中々ダイレクトでマッチする機能は探せず。
当時はそんなに時間もなかったのでUE4で実現するのをあきらめていました。
そんな中ネットを見ているとUnityならドンピシャの機能を作られている方がいて、試してみると普通にやりたい事ができてしまい感動した記憶があります。
Unity で Windows のデスクトップ画面をテクスチャとして表示するプラグインを作ってみた - 凹みTips
凄い凄いと思いながら、Unityでも実現できてるんだからUnrealでも作れるんじゃないだろうかと思い、トライしてみたのが始まりです。
Windowをキャプチャーする 私は25歳の時に今で言う「未経験からエンジニア」で転職したのですが、その時最初にやった業務がWindows上でのウィンドウキャプチャーでした。
C++, MFCで戦っていたのですが、当時はHDC? HWND?何それ?メモリDCってなに?って感じだったのを覚えています。
そのためウィンドウをキャプチャーするという技術には特別な思いがあります。
キャプチャー方法 私の知っているウィンドウキャプチャー方法は以下の2つです。
WindowのDCを取得してBitBlt WindowのDCを取得してPrintWindow 速度的にはBitBltの方がPrintWindowよりも早くて良いのですが、ChromeやUE4で作ったアプリケーションなどはBitBltではキャプチャーできません。
Windowを直接キャプチャーするのではなく、デスクトップのDCからキャプチャーして必要な領域をトリミングすると、どんなウィンドウでもキャプチャーできるのですが、 キャプチャーするのにディスプレイモニターのリフレッシュレート分待たされてしまう問題や、重なったウィンドウの背面側はキャプチャーできない等問題も数多くありました。
もう一つのPrintWindowも当初はChromeのキャプチャーはできないと思っていたのですが、Microsoftのヘルプに載っていない引数(PW_RENDERFULLCONTENT=2)を与えるとキャプチャーできるようになる発見がありました。
そこで今回はPrintWindowで作ってみる事にしました。
(その他にDirectXを使ってウィンドウキャプチャーする方法もあるそうですが、これはまだ試していません)
UE4での実装 とりあえずTickの中でターゲットのウィンドウをキャプチャーしてテクスチャの中身を書き換えてみました。
テクスチャー(UTexture2D)の書き換えは以下のコードで実現できます。
auto Region = new FUpdateTextureRegion2D(0, 0, 0, 0, TextureTarget->GetSizeX(), TextureTarget->GetSizeY()); TextureTarget->UpdateTextureRegions(0, 1, Region, 4 * TextureTarget->GetSizeX(), 4, (uint8*)m_BitmapBuffer); TextureTargetがターゲットとなるTexture2Dで、 m_BitmapBufferはBGRA形式のピクセルバッファです。
この2行で動的にテクスチャーの書き換えができます。
実行するとうまくいったかのように見えたのですが、対象のウィンドウのサイズが大きくなるとカクツキが酷くなってしまい困りました。
{{< x user=“ayuma_x” id=“1137004503868223491” >}}
そこで次はキャプチャーの部分のみTaskを使ってバックグラウンドで処理してみました。
void ACaptureMachine::Tick() { AsyncTask(ENamedThreads::BackgroundThreadPriority, [this]() { // キャプチャー処理を実施 }); } そうすると先ほどよりもフレームレートが上がり効果がありましたので、次に複数ウィンドウのキャプチャーにトライしました。
...