07.Java側で作成したGL_TEXTURE_EXTERNAL_OESのテクスチャを、Unity側で作成したGL_TEXTURE_2Dのテクスチャに転写する方法

前の項までで、以下が判明した。
・Java側のSurfaceTextureのテクスチャは、GL_TEXTURE_EXTERNAL_OESをターゲットとしてバインドできるテクスチャである必要がある。
・Unity側のテクスチャは、GL_TEXTURE_2Dをターゲットとしてバインドできるテクスチャである必要がある。

したがって、「Android(Java)のSurfaceTextureのテクスチャをUnityで描画する方法」として、「Java側でGL_TEXTURE_EXTERNAL_OES のテクスチャを作成し、SurfaceTextureに割り付ける。Unity側で表示する際には、Java側で作成した GL_TEXTURE_EXTERNAL_OES のテクスチャの画像を、Unity側で作成した GL_TEXTURE_2Dのテクスチャに転写する」方法に辿り着く。

結果としては、成功。この方法はうまくいった。

解説

Java側で作成したGL_TEXTURE_EXTERNAL_OESのテクスチャを、Unity側で作成したGL_TEXTURE_2Dのテクスチャに転写するために、すべきことは、以下です。

実装

プロジェクトを開く

06.Java側で作成したGL_Texture_2Dのテクスチャを、Unity側で扱うことができることのテスト」を実施していない場合は、実施します。

Javaクラスの編集:06.で加えた変更を元に戻す

Androidライブラリのプロジェクトを開きます。

06.Java側で作成したGL_Texture_2Dのテクスチャを、Unity側で扱うことができることのテスト」でSurfaceの初期化の関数に加えた変更を元に戻します。

Surfaceの初期化 initSurface関数の内容を以下のようにします。


06.Java側で作成したGL_Texture_2Dのテクスチャを、Unity側で扱うことができることのテスト」でSurfaceでの描画の関数に加えた、「関数内の処理をすべてコメントアウト」を解除します。

Surfaceの描画 drawInSurface関数の内容を以下のようにします。

Javaクラスの編集(不使用関数の削除)

Android側で作成したテクスチャのIDの取得 getAndroidTextureID関数は、使用しないので、削除します。

Javaクラスの編集:初期化処理まとめ関数の追加

Javaクラスの末尾に、以下の初期化処理をまとめて呼び出す関数を追加します。


Surfaceの初期化 initSurface関数は、クラス外部から呼び出せないように、アクセス修飾子を、「public」から「private」に変更します。

Javaクラスの編集:シェーダープログラムの構築処理の追加

Javaクラスの定数部に、シェーダーコードを追加します。
Javaクラスのメンバー変数部に、シェーダープログラムに関する変数を追加します。


Javaクラスの末尾に、以下のシェーダープログラムの構築に関する関数を追加します。


初期化処理をまとめて呼び出す関数 init関数の末尾に、「シェーダープログラムの初期化」関数の呼び出しを追加します。

Javaクラスの編集:フレームバッファオブジェクトを構築する処理の追加

Javaクラスのメンバー変数部に、フレームバッファオブジェクト変数を追加します。


Javaクラスの末尾に、以下の「フレームバッファオブジェクトの初期化」関数を追加します。


初期化処理をまとめて呼び出す関数 init関数に、「フレームバッファオブジェクトの初期化」関数の呼び出しを追加します。

Javaクラスの編集:頂点バッファオブジェクトを構築する処理の追加

Javaクラスの定数部に、float型のサイズの定数を追加します。
Javaクラスのメンバー変数部に、頂点バッファオブジェクト変数を追加します。


Javaクラスの末尾に、以下の頂点バッファオブジェクトの構築に関する関数を追加します。


初期化処理をまとめて呼び出す関数 init関数の末尾に、「頂点バッファオブジェクトの初期化」関数の呼び出しを追加します。

Javaクラスの編集:Androidテクスチャをフレームバッファーオブジェクトに描画

Javaクラスのメンバー変数部に、テクスチャ描画に関する変数を追加します。


Javaクラスの末尾に、以下の「Androidテクスチャをフレームバッファーオブジェクトに描画」関数を追加します。


初期化処理をまとめて呼び出す関数 init関数に、「クリア色の指定」の処理を追加します。


SurfaceTextureの更新 updateSurfaceTexture関数に、「SurfaceTexture変換行列の取得」処理、「Androidテクスチャをフレームバッファーオブジェクトに描画」関数の呼び出しを追加します。


「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。

Androidライブラリモジュールのビルド

Androidライブラリモジュールをビルドします。

「Gradle」ウィンドウの「SurfaceTextureRendererProject > surfacetexturerenderer > Tasks > build > build」をダブルクリックします。

モジュールのビルドが開始します。
しばらく待ちます。
Android Studio のステータスバーに「Gradle build finished in ・・・」と出るまで待ちます。

「{Androidプロジェクトフォルダ}\{Androidライブラリモジュール名}\build\outputs\aar」フォルダに、リリースビルド、デバッグビルドの2つの「aar」ファイルが生成されます。

aarファイルの配置

Androidライブラリモジュールのファイル(aarファイル)を、Unityアプリのプロジェクトに配置します。

「{Unityプロジェクトフォルダ}\Assets\Plugins\Android」フォルダに、
「{Androidプロジェクトフォルダ}\{Androidライブラリモジュール名}\build\outputs\aar」フォルダに生成済みの「aar」ファイルのリリースビルドの方を、コピ-します。

Unityスクリプトの編集:06.で加えた変更を元に戻す

Unityアプリのプロジェクトを開きます。

06.Java側で作成したGL_Texture_2Dのテクスチャを、Unity側で扱うことができることのテスト」でイベント処理の関数に加えた変更を元に戻します。

イベント処理 OnEvent関数の内容を以下のようにします。

Unityスクリプトの編集:Rendererの初期化関数の変更

Rendererの初期化で呼び出すJava側の初期化関数を「initSurface」から「init」に変更します。

TextureRendererの初期化 InitializeTextureRenderer関数の内容を以下のようにします。

実行

Build And Run

Unityアプリのプロジェクトを開きます。

Android端末をUSB接続しておきます。

メインメニュー「File > Build And Run」を選択します。

Unityアプリのビルドが開始し、ビルドが終了すると、Android端末上でUnityアプリが実行されます。

起動直後


アプリ画面のボタンを押します。
TextureRendererの初期化処理が実行されます。

アプリ画面のボタンを再度押します。
テクスチャの更新処理が実行されます。

UnityアプリのRawImageの描画に変化があり、Surfaceで描画した内容が描画されました。
(背景:濃い青色
 四角形:黄緑色、左上(100, 200)、右下(300, 400)
 円:黄色、中心(300,400)、半径100、線の太さ30
 ※ (0, 0)の位置は、テクスチャ画像領域の左上)
 


「Android Logcat」ウィンドウを確認すると、エラーは発生していません。

考察

前の項までで、以下が判明していた。
・Java側のSurfaceTextureのテクスチャは、GL_TEXTURE_EXTERNAL_OESをターゲットとしてバインドできるテクスチャである必要がある。
・Unity側のテクスチャは、GL_TEXTURE_2Dをターゲットとしてバインドできるテクスチャである必要がある。

したがって、「Android(Java)のSurfaceTextureのテクスチャをUnityで描画する方法」として、「Java側でGL_TEXTURE_EXTERNAL_OES のテクスチャを作成し、SurfaceTextureに割り付ける。Unity側で表示する際には、Java側で作成した GL_TEXTURE_EXTERNAL_OES のテクスチャの画像を、Unity側で作成した GL_TEXTURE_2Dのテクスチャに転写する」方法に辿り着く。

結果としては、成功。この方法はうまくいった。

関連ページ

前項目:06.Java側で作成したGL_Texture_2Dのテクスチャを、Unity側で扱うことができることのテスト

前項目:08.変化する画像を連続で描画