【Unity】【C#】Unity4 Free版で RenderTexture のようなオフスクリーンレンダリングをして、ユニティちゃんステージのバックスクリーンを作る 
2015/07/12 Sun [edit]
Unity5 では、Unity4 で制限されていた機能が Free版(Personal版と改名)でも使えるのだが、どうも Unity5 と Unity4 ではライトやシェーダーの仕様が変更されたようで、プロジェクトによっては上手くアップグレードされず、見た目がおかしくなってしまうものも多い。
そんなわけで Unity4 のまま、ユニティちゃんステージのバックスクリーンが使えないかな~と思って調べてみたら、いくつか資料があったので、色々試してみたらそこそこ上手くいった。
(参考)
・Render Camera To Texture Unity Free (You Tube)
・Unityのオフスクリーンレンダリング
●カメラの映像をテクスチャに映し出すスクリプト(Fullscreen[可変]対応)
using UnityEngine;
using System.Collections;
public class RenderCameraToTexture : MonoBehaviour {
Texture2D renderedTexture;
public Material mat; //出力先
Rect rect; //領域用
public int width = 512; //映像領域のサイズ
public int height = 512;
public TextureFormat format = TextureFormat.ARGB32; //ARGB32 or RGB24
//Fullscreen(可変)対応
public int orgScrWidth = 960; //オリジナル画面サイズ(基準サイズ)
public int orgScrHeight = 540;
int oldScrWidth; //画面サイズ変更チェック用
int oldScrHeight;
// Use this for initialization
void Awake () {
orgScrWidth = (orgScrWidth <= 0) ? Screen.width : orgScrWidth;
orgScrHeight = (orgScrHeight <= 0) ? Screen.height : orgScrHeight;
width = (width <= 0) ? Screen.width : width;
height = (height <= 0) ? Screen.height : height;
createTexture(width, height);
oldScrWidth = orgScrWidth;
oldScrHeight = orgScrHeight;
}
void OnPostRender () {
//Fullscreen(可変)対応
if (oldScrWidth != Screen.width || oldScrHeight != Screen.height) {
int w = width * Screen.width / orgScrWidth;
int h = height * Screen.height / orgScrHeight;
createTexture(w, h);
}
oldScrWidth = Screen.width;
oldScrHeight = Screen.height;
renderedTexture.ReadPixels(rect, 0, 0, false);
renderedTexture.Apply();
}
//映像用テクスチャを準備する
void createTexture(int w, int h) {
renderedTexture = new Texture2D(w, h, format, false);
mat.mainTexture = renderedTexture;
rect = new Rect(0, 0, w, h);
}
}
内容的には、参考資料の You Tube 動画の中のコードと、Qiita のコードを混ぜあわせたもの。資料の説明にある通り、このやり方は非常にパフォーマンスが悪いので、色々なパターンを試したら、上記のコードのような感じが一番良かった。
やってみて非常にパフォーマンスが改善されたのは、動画中の Texture2D のコンストラクタを Texture2D(width, height) としないで、Texture2D(width, height, format, false) の方を使い、mipmap をオフにすることだ。オフスクリーンサイズが固定ならば必要もない。
あとは単純にスクリーンを読み込むサイズを Screen.width, Screen.height から、なるべく小さいサイズにすること。サンプルでは 512x512 にしているが、256x256 だと、だいぶ速くなる。しかしもちろんサイズが狭いので、動きが大きいものでは上手く追従できなくなるので注意。ただし、このサイズ固定のやり方だと、画面サイズを変更したときスケールが異なってしまい、映し出す領域が違ってしまう欠点がある。なので、基準となる元の画面サイズと現在の画面サイズを比較して、映し出す領域を比率で再計算するようにした。
あと OnPostRender() の呼び出し回数をカウントして、数回おきに更新する方法もやってみたが、あまり効果はなかった。むしろ2~3回おきに更新ではパフォーマンスは悪く、6回おき以上にすれば良くなるが、バックスクリーンがカクカクしたコマ送り状態になるのでやめた。あまり動きがないものには効果的かも知れないが、思ったより良くはならない(少なくとも見た目は)。といってもテストしているのは PC なので、Android や iPhone ではまた事情が違うだろう。たぶん PC の場合は CPU や GPU のハードウェアキャッシュやレンダリングパイプラインなどで高速化されているので、そのままの方が速いのかも知れない。
Texture2D のテクスチャフォーマットは ARGB32 と RGB24 の2種類しか使えないが、PC ではどちらも変わらない。スマホなどメモリの少ない端末なら RGB24 も効果があるかも知れないが、試してみるのが一番だろう。
使い方は映像を取得したいカメラにスクリプトを追加して、映像の出力先となるマテリアルを登録するだけだ。width と height は0にすると画面いっぱいのサイズになるので、必要なだけのサイズに設定しておこう。ここでは、ユニティちゃん Candy Rock Star コンサートプロジェクトのバックスクリーン用カメラ「Back Screen Camera」に使用することとする。他のテクスチャに出力しても構わない。

※全て設定し終えたら(Apply)、プレファブは削除して良い
●「RenderCameraToTexture」スクリプトを追加して設定する

●出力先マテリアルを選択する

以上でOK。
まぁ、おとなしく Unity5 使えって感じでもあるけどね。5なら床の鏡面反射もデフォルトで使えるし。とはいえ、Unity4 で作ったプロジェクトを5でそのまま読み込んでも、変な影が付いたり、光の加減が強すぎたり、一部のシェーダが機能してないで、別の何かになってたりと(笑)、移行するにはしばらく時間かかりそう。そういえば昔、PhotoShop なんかもメジャーバージョン変わったときに、古いファイルが上手く再現できないことがあったけど(フォントサイズとかレイヤー効果やブレンド値など)、バージョンアップもなかなか大変なものだな…。
(関連記事)
【Unity】プロ生ちゃんを動かす!
【Unity】SDプロ生ちゃんを動かす!

- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/186-da3909c3
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |