【Unity】AndroidでCubemapを使ったShaderが表示されないとき
Materialが黒くなって正しく表示されない
Editor上では問題のないMaterialが実機上だとうまく表示されないことがままあります。
今回もまさにそのパターンで自作ShaderのSkyboxがうまく機能しなかったので、自分用覚書に。
症状としてはMaterialが問答無用に真っ黒になる、というものでした。
MaterialからShaderが外れているならば、紫になるはずなので、真っ黒ならShader自体はくっついているはずです。
原因はGraphicsAPIに
Edit>GraphicsEmulationを見てみましょう。
何もいじっていなければUnity5.4.1f現在、OpenGL ES2.0になっているはずです。
一方で、PlayerSettingsを開いてOtherSettings>AutoGraphicsAPIにチェックがついているのを確認してください。
犯人はそいつです。チェックを外してみるとおそらく次のようになっています。
ここからOpenGLES3を外してやればUnityEditor上の表示と一致するはずです。
参考(情報元)
【Unity】【VR】立体視の原理から考える天球画像と3Dリアルタイムレンダリングの差異
VRにおける天球画像と3Dリアルタイムレンダリング
はじめに
本記事ではVRにおいて、あるシーンを実際にUnity上でプレイして見た場合とそのシーンを天球画像としてキャプチャし、skyboxとしてUnity上で見た場合の違いについて取り扱います。
便宜的に前者を「リアルタイムレンダリングで見た場合」、後者を「天球画像で見た場合」としています。
言い回しとして正しくないのは承知の上ですが、ご了承ください。
天球画像への疑問
前置きが長くなりましたが、
例えばUnity上でオブジェクトを置いて、それをVRで見るのと、
そのシーンをカメラの位置から360度キャプチャしてskyboxにして見るのは何が違うのでしょうか。
※ポジショントラッキングをした場合の差異については置いておきます。
リアルタイムレンダリングで見た場合の優位性
結論から言って、立体視が違います。
天球画像で見た場合、左右の眼に映る画像に違いがないので、どこかのっぺりと見えます。
これは物が近くにあればあるほど、顕著です。
このあたりの知見は拙文ながら私の過去記事もちょっと関係があることを書いています。
天球画像で立体視は可能なのか
左右に違う天球画像を出してみる
では左右ですこしずらした天球画像をだしてみましょう。 前項の推測が正しければ、これで立体視できるはずです。
やったことは単純で、
- 左右の眼の位置に合わせて、少しずらして二枚の天球画像をキャプチャする。*1
- 左右のカメラにそれぞれskyboxを設定する。
以上です。
この手法の限界
結論から言って、この手法では正面以外が破綻します。
原因は目の位置にあります。
次の図を見てください。
左が人間がいつも見ている見え方です。
対して天球画像二枚手法では完璧な模倣が出来ていないことがわかります。
この状態でオキュラスでみるとチカチカするはずです。しました。
なお、正面(と真後ろ)だけは完璧に模倣できているため、ちゃんと見えます。
まとめ
2016/10/29追記
聞くところによると360動画でも立体視する方法はあるとのこと。調査しだい記事にいたします。
2016/11/25追記
記事にしました。
ユニティちゃんトゥーンシェーダーを使ってみてハマったところ
使った環境
- Windows8.1
- Unity5.4.f1
- UnityChanToonShader_v1.0.1
設定わからない問題
マニュアル見ましょう。とても詳しく書いてあります。
マニュアル見つからない問題
こんなの私しかハマらないと思いますが、ここです。 教訓 思考放棄してAssets以下のunitypakcageダブルクリックしない。
色が暗くなってしまう問題
AmbientLightの問題みたいです。
どうやらAmbientSourceはColorがイイみたいです。skyboxだと反応しませんでした。
これを
こう設定します。
なぜかAmbientSourceをColorにして設定してからskyboxに戻しても設定したColorのライティングが生きてます。(バグ?)
最適な感じわからない問題
最適な絵というものはないです。
という回答は私がもらって困ったので、
個人的に参考にしたいと思っているものを、、
Muroさんの作成物
twitter.com
あとはいろんな人に見てもらうのがいいのかなと。
【Unity】VRのカメラにおける距離感with天球画像
VRで感じる「大きさ」を考えてみる
はじめに
本記事は実際にやってみてこうだろう、という記事です。
細かいところには間違いがあるかもしれません。ぜひご指摘いただければ幸いです。
VRにおける大きさの誤認
例えば天球画像で部屋を作ったとします。
その中に60m四方のキューブをひとつ、90m離して出したとき、人はそのキューブを60m四方だと感じるのか。
答えはNOです。
人の脳は天球の情報量から大きさを推測し、キューブとの距離感を正しく認識できません。
VRに限ったことではないですが、
椅子や机の天球に騙されて大きさを正しく認識できません。
つまり、
「すごく大きな部屋にいて、60mクラスの大きな箱が遠くにある」と感じるのではなく、
「普通の大きさの部屋にいて、せいぜい2mくらいの箱が近くにある」と感じます。
距離感ってなんだっけ
そもそも距離感は比較で語られるはずです。
ですから、比較する対象がなければ、
単純には1m離れたところの1m四方のキューブと2m離れたところの2m四方のキューブは同じ大きさに見えるはずです。
緑のキューブと青のキューブの大きさは同じにみえるはず。
実際に試してみる
実際にUnity上で試してみます。
まず、VRSupportedをオフにして試してみます。
VRSupportedオフの場合
カメラの位置からみると二枚のパネルが完全に同じ大きさにみえて重なっているのがわかります。
手前の緑の半透明のパネルを消してみます。
手前のパネルを元に戻して奥の青のパネルを消します。
これをVRで試します。
VRSupportedオンの場合
実行してみると先ほどと違い、ずれているのがわかります。
これはなぜでしょうか。
立体視の仕組みを考える。
基本に立ち返ると、人は目に映るものの差で立体としてものを見ます。
したがって以下の図のように見えているのです。
これは単体のカメラより大きさを正しくとらえられているとも言えます。
ちなみにエディタのウィンドウには左目の映像が出ています。
立体視ができれば大きさを正しく認識できるのか
答えはNoのようです。テストのように著しく情報の少ない状況かつ、きわめて視差を取りづらい中で正しく距離感を得ることは難しいようです。
VRにおけるスケール感のカギ
以上のテストから、
- VRは立体視、ディスプレイより物の大きさをしっかりととらえる(距離の差を理解して完璧に重なって見えたりしない)
- とはいえやはり周りの状況にも引っ張られる。
といった知見を得ました。
やはりVRという架空の世界において物の大きさを感じさせるには、周りのもので情報を与えてあげる必要があるようです。
ユーザーに感じてほしい大きさを感じてもらうためには周りの比較対象を正しく選ぶことが肝要と言えるみたいです。
【失敗談】Unity用にVisualStudioでUMLを自動生成したかった
UML生成自動化の試み
事の発端はUnityでプロジェクトを進める上でUMLを自動生成できたらいいなぁと思ってVisualStudio上でDSLを実行しようとしたことです。
失敗した原因
無料版のVisualStudioはDSLをサポートしてない。
というわけで無料で行いたい方は回れ右です。
以下、失敗談。
VisualStudioでDSLを扱う
セットアップ
- VisualStudioSDKのインストールをする。
相変わらず日本語翻訳がやや残念な気がしますがMicroSoftの公式サポートはこちら
コントロールパネル->プログラム->プログラムと機能->MicroSoft VisualStudio->変更をするとVisualStudioが立ち上がるので、VisualStuioExtensibilityToolsUpdateにチェックをしてNextします。 - Modeling SDK for Visual Studioをインストールする。
こちらがVisualStudioのDSL拡張本体です。
公式サポート
ダウンロードはこちら
- DSLのプロジェクトを作ってみる。
VisualStudioのファイルから作成可能です。うまくいっていれば機能拡張の欄が画像のようになっているはずです。
いざ!OK
あっ...(察し)
参考にしたかった記事様
Visual Studio 2012でDSL(Domain Specific Langage)を実践 様
Visual Studio 2013でDSLを実践する 様
初心者の(筆者が)始めるPlantUML
PlantUMLを使ってみる
※適宜読み飛ばしてください。
筆者のあれこれ
その前にUMLとは
統一モデリング言語(とういつモデリングげんご、UML、英: Unified Modeling Language)は、主にオブジェクト指向分析や設計のための、記法の統一がはかられた(Unified)モデリング言語(Modeling Language)である。
wikipediaより引用
プログラミングの世界では歴史的に長いこと設計文書の書式の統一化が図られていませんでした。そこで偉い人たちが集まって決めた世界標準言語がUMLです。
詳しくはググってみるとたくさん出てきます。
例えば UML超入門様
PlantUMLの大体
ざくっといえばテキストベースでUMLを書けるツールです。詳しくはプログラマーズ雑記帳様などが詳しく解説をくださっています。
しかし(私にとって)特に重要なのは
- 短時間で世界標準の図が書ける
- テキストベースのお作法を守れば間違った図にはそうそうならない
以上です。
間違った図になりにくいことということは、勉強用にも適していることにもなります。
使うメリット
UMLひいてはPlantUMLを使うメリットは私ではあげきれないほどありますが、例えばクラス図であれば典型的には
以上辺りでしょうか。
本記事を書くにあたって影響をうけたグローバルゲームジャムでクラス設計をやったらスムーズに開発が進んだ話様でも有用性が示されています。
いざ導入
今回はAtomとPlantUMLで爆速UMLモデリング様を参考にして進めました。
筆者の環境は
- Windows8.1
入ってなければインストールするものは
apm install plantuml-viewer
apm install language-plantuml
としてやると楽です。
書き方
簡単なものであればPlantUML Cheat Sheet様が参考になります。
公式の解説はこちら
例えばこんな風に循環参照してしまっている箇所がビジュアル的に見て取れたりします。素晴らしい!
まとめ(意気込み)
Unityでちょっとした初期化などを事前に行う
インスペクタから変更できないSerializeを行う。
Monobehaviorを継承したクラスで、[SerializeField]アトリビュートをつけると、シリアライズできるのは良いのですが、 初めに参照を設定したら後はインスペクタから変更できないようにしておきたい場合もあると思います。 そんな時の対処法の一つです。
void Awake()より早く設定できることや、実行時に(極小ですが)GetConponentしない分有利です。(当然かわりにシリアライズ分のデータはかかるとして)
方針
- [SerializeField,HideInspector]アトリビュートでシリアライズできるけどインスペクタからは見えないメンバをつくっておく。
- void Reset()によってアタッチした瞬間に参照関係を設定
- おまけにvoid Awake()に一応Assertを入れてあげる
まずはコード
たとえば同オブジェクトにアタッチされたカメラを取得するなら次のようなコードになります。
using UnityEngine; public class CameraController : MonoBehaviour { [SerializeField,HideInInspector] Camera camera_; void Reset () { camera_ = this.GetComponent<Camera>(); } void Awake () { Debug.Assert(camera_ != null); } //以下適当なコード }
ちなみにアタッチするとこんな感じになります。
[SerializeField]や[HideInspector]について
アトリビュート全般に関してはテラシュールブログ様がとてもわかりやすい記事をくださっています。 ここで重要なのは
- [SerializeField]でメンバはシリアライズできる
- [HideInspector]でメンバはインスペクタ上からは見えなくなる
以上の二点です。
void Reset()について
公式のリファレンスに素晴らしく簡潔にわかりやすく記述してくださっています。 ここで重要なのは
- void Reset()はエディタ上でスクリプトをオブジェクトにアタッチした際に呼ばれる。
という一点です。
Assertについて
void Awake()内にAssertを書くことで、万が一うまくシリアライズできていない場合にエラーを出してわかるようにしておきます。 Assertは引数がfalseになるとエラーを出してくれて、かつリリース時にはコンパイルされません。(つまりデバッグ中だけ動作する。)
応用について
これを応用して簡易的に事前に計算できるものは事前に計算したりすることが可能です。
とても初歩的かつ地味な内容でしたが、お読みいただきありがとうございました。