akyboxブログ

旧AkiIroブログ

【Unity】AndroidでCubemapを使ったShaderが表示されないとき

Materialが黒くなって正しく表示されない

Editor上では問題のないMaterialが実機上だとうまく表示されないことがままあります。
今回もまさにそのパターンで自作ShaderのSkyboxがうまく機能しなかったので、自分用覚書に。 症状としてはMaterialが問答無用に真っ黒になる、というものでした。

MaterialからShaderが外れているならば、紫になるはずなので、真っ黒ならShader自体はくっついているはずです。

原因はGraphicsAPIに

Edit>GraphicsEmulationを見てみましょう。
何もいじっていなければUnity5.4.1f現在、OpenGL ES2.0になっているはずです。
f:id:AkiIro:20161106165451p:plain
一方で、PlayerSettingsを開いてOtherSettings>AutoGraphicsAPIにチェックがついているのを確認してください。
犯人はそいつです。チェックを外してみるとおそらく次のようになっています。
f:id:AkiIro:20161106165736p:plain
ここからOpenGLES3を外してやればUnityEditor上の表示と一致するはずです。

参考(情報元)

answers.unity3d.com

【Unity】【VR】立体視の原理から考える天球画像と3Dリアルタイムレンダリングの差異

VRにおける天球画像と3Dリアルタイムレンダリング

はじめに

本記事ではVRにおいて、あるシーンを実際にUnity上でプレイして見た場合とそのシーンを天球画像としてキャプチャし、skyboxとしてUnity上で見た場合の違いについて取り扱います。

便宜的に前者を「リアルタイムレンダリングで見た場合」、後者を「天球画像で見た場合」としています。

言い回しとして正しくないのは承知の上ですが、ご了承ください。

天球画像への疑問

前置きが長くなりましたが、

例えばUnity上でオブジェクトを置いて、それをVRで見るのと、

そのシーンをカメラの位置から360度キャプチャしてskyboxにして見るのは何が違うのでしょうか。

※ポジショントラッキングをした場合の差異については置いておきます。

リアルタイムレンダリングで見た場合の優位性

結論から言って、立体視が違います。

天球画像で見た場合、左右の眼に映る画像に違いがないので、どこかのっぺりと見えます。

これは物が近くにあればあるほど、顕著です。 f:id:AkiIro:20161028030518p:plain

このあたりの知見は拙文ながら私の過去記事もちょっと関係があることを書いています。

akiiro.hatenablog.com

天球画像で立体視は可能なのか

左右に違う天球画像を出してみる

では左右ですこしずらした天球画像をだしてみましょう。 前項の推測が正しければ、これで立体視できるはずです。

やったことは単純で、

  1. 左右の眼の位置に合わせて、少しずらして二枚の天球画像をキャプチャする。*1
  2. 左右のカメラにそれぞれskyboxを設定する。

以上です。

この手法の限界

結論から言って、この手法では正面以外が破綻します。

原因は目の位置にあります。

次の図を見てください。

f:id:AkiIro:20161028032202p:plain

左が人間がいつも見ている見え方です。

対して天球画像二枚手法では完璧な模倣が出来ていないことがわかります。

この状態でオキュラスでみるとチカチカするはずです。しました。

なお、正面(と真後ろ)だけは完璧に模倣できているため、ちゃんと見えます。

まとめ

2016/10/29追記

聞くところによると360動画でも立体視する方法はあるとのこと。調査しだい記事にいたします。

2016/11/25追記

記事にしました。

akiiro.hatenablog.com

*1:具体的には人の瞳孔間距離にあわせて6cmほど横にずらします。

*2:少なくともこの手法では

ユニティちゃんトゥーンシェーダーを使ってみてハマったところ

使った環境

  • Windows8.1
  • Unity5.4.f1
  • UnityChanToonShader_v1.0.1

設定わからない問題

マニュアル見ましょう。とても詳しく書いてあります。

マニュアル見つからない問題

こんなの私しかハマらないと思いますが、ここです。 f:id:AkiIro:20161015200154p:plain 教訓 思考放棄してAssets以下のunitypakcageダブルクリックしない。

色が暗くなってしまう問題

AmbientLightの問題みたいです。
どうやらAmbientSourceはColorがイイみたいです。skyboxだと反応しませんでした。
これを
f:id:AkiIro:20161015201154p:plain
こう設定します。
f:id:AkiIro:20161015201243p:plain
なぜかAmbientSourceをColorにして設定してからskyboxに戻しても設定したColorのライティングが生きてます。(バグ?)

最適な感じわからない問題

最適な絵というものはないです。

という回答は私がもらって困ったので、 個人的に参考にしたいと思っているものを、、

Muroさんの作成物
twitter.com

ギルティギア
www.youtube.com

あとはいろんな人に見てもらうのがいいのかなと。

【Unity】VRのカメラにおける距離感with天球画像

VRで感じる「大きさ」を考えてみる

はじめに

本記事は実際にやってみてこうだろう、という記事です。
細かいところには間違いがあるかもしれません。ぜひご指摘いただければ幸いです。

VRにおける大きさの誤認

例えば天球画像で部屋を作ったとします。
その中に60m四方のキューブをひとつ、90m離して出したとき、人はそのキューブを60m四方だと感じるのか。
答えはNOです。
人の脳は天球の情報量から大きさを推測し、キューブとの距離感を正しく認識できません。 f:id:AkiIro:20161015052208p:plain VRに限ったことではないですが、
椅子や机の天球に騙されて大きさを正しく認識できません。
つまり、
「すごく大きな部屋にいて、60mクラスの大きな箱が遠くにある」と感じるのではなく、
「普通の大きさの部屋にいて、せいぜい2mくらいの箱が近くにある」と感じます。

距離感ってなんだっけ

そもそも距離感は比較で語られるはずです。
ですから、比較する対象がなければ、
単純には1m離れたところの1m四方のキューブと2m離れたところの2m四方のキューブは同じ大きさに見えるはずです。
f:id:AkiIro:20161014232654p:plain
緑のキューブと青のキューブの大きさは同じにみえるはず。

実際に試してみる

実際にUnity上で試してみます。
まず、VRSupportedをオフにして試してみます。

VRSupportedオフの場合

カメラの位置からみると二枚のパネルが完全に同じ大きさにみえて重なっているのがわかります。
f:id:AkiIro:20161015044519p:plain 手前の緑の半透明のパネルを消してみます。
f:id:AkiIro:20161015044734p:plain 手前のパネルを元に戻して奥の青のパネルを消します。
f:id:AkiIro:20161015044824p:plain これをVRで試します。

VRSupportedオンの場合

実行してみると先ほどと違い、ずれているのがわかります。 f:id:AkiIro:20161015045131p:plain これはなぜでしょうか。

立体視の仕組みを考える。

基本に立ち返ると、人は目に映るものの差で立体としてものを見ます。
したがって以下の図のように見えているのです。
f:id:AkiIro:20161015045814p:plain
これは単体のカメラより大きさを正しくとらえられているとも言えます。
ちなみにエディタのウィンドウには左目の映像が出ています。

立体視ができれば大きさを正しく認識できるのか

答えはNoのようです。テストのように著しく情報の少ない状況かつ、きわめて視差を取りづらい中で正しく距離感を得ることは難しいようです。

VRにおけるスケール感のカギ

以上のテストから、

  • VRは立体視、ディスプレイより物の大きさをしっかりととらえる(距離の差を理解して完璧に重なって見えたりしない)
  • とはいえやはり周りの状況にも引っ張られる。

といった知見を得ました。
やはりVRという架空の世界において物の大きさを感じさせるには、周りのもので情報を与えてあげる必要があるようです。
ユーザーに感じてほしい大きさを感じてもらうためには周りの比較対象を正しく選ぶことが肝要と言えるみたいです。

【失敗談】Unity用にVisualStudioでUMLを自動生成したかった

UML生成自動化の試み

事の発端はUnityでプロジェクトを進める上でUMLを自動生成できたらいいなぁと思ってVisualStudio上でDSLを実行しようとしたことです。

失敗した原因

無料版のVisualStudioはDSLをサポートしてない。

というわけで無料で行いたい方は回れ右です。

以下、失敗談。

VisualStudioでDSLを扱う

セットアップ

  1. VisualStudioSDKのインストールをする。
    相変わらず日本語翻訳がやや残念な気がしますがMicroSoftの公式サポートはこちら
    コントロールパネル->プログラム->プログラムと機能->MicroSoft VisualStudio->変更をするとVisualStudioが立ち上がるので、VisualStuioExtensibilityToolsUpdateにチェックをしてNextします。
    f:id:AkiIro:20160925153000p:plain
  2. Modeling SDK for Visual Studioをインストールする。
    こちらがVisualStudioのDSL拡張本体です。
    公式サポート
    ダウンロードはこちら
    f:id:AkiIro:20160925153351p:plain
  3. DSLのプロジェクトを作ってみる。
    VisualStudioのファイルから作成可能です。うまくいっていれば機能拡張の欄が画像のようになっているはずです。
    f:id:AkiIro:20160925155451p:plain
    いざ!OK
    f:id:AkiIro:20160925155831p:plain
    あっ...(察し)
    f:id:AkiIro:20160925160633p:plain

    参考にしたかった記事様

    Visual Studio 2012でDSL(Domain Specific Langage)を実践 様
    Visual Studio 2013でDSLを実践する 様

初心者の(筆者が)始めるPlantUML

PlantUMLを使ってみる

※適宜読み飛ばしてください。

筆者のあれこれ

  • UMLこてこて初心者
  • PlantUMLを使ってUML自体も勉強したい
  • プロジェクト上での運用を目指す

その前にUMLとは

統一モデリング言語(とういつモデリングげんご、UML、英: Unified Modeling Language)は、主にオブジェクト指向分析や設計のための、記法の統一がはかられた(Unified)モデリング言語(Modeling Language)である。

wikipediaより引用

プログラミングの世界では歴史的に長いこと設計文書の書式の統一化が図られていませんでした。そこで偉い人たちが集まって決めた世界標準言語がUMLです。

詳しくはググってみるとたくさん出てきます。

例えば UML超入門様

PlantUMLの大体

ざくっといえばテキストベースでUMLを書けるツールです。詳しくはプログラマーズ雑記帳様などが詳しく解説をくださっています。

しかし(私にとって)特に重要なのは

  • 短時間で世界標準の図が書ける
  • テキストベースのお作法を守れば間違った図にはそうそうならない

以上です。

間違った図になりにくいことということは、勉強用にも適していることにもなります。

使うメリット

UMLひいてはPlantUMLを使うメリットは私ではあげきれないほどありますが、例えばクラス図であれば典型的には

  • 保守・拡張が容易になる。(そもそも規模が大きくなればドキュメントは必須)
  • チームでの作業の分担が容易になる。
  • 俯瞰的にアーキテクチャを見つめ直すことでリファクタリングの必要に気づける。

以上辺りでしょうか。

本記事を書くにあたって影響をうけたグローバルゲームジャムでクラス設計をやったらスムーズに開発が進んだ話様でも有用性が示されています。

いざ導入

今回はAtomとPlantUMLで爆速UMLモデリング様を参考にして進めました。

筆者の環境は

入ってなければインストールするものは

  1. Atom サイトはこちら
  2. Java サイトはこちら
  3. Graphviz サイトはこちら
  4. Atomの次のパッケージ二つ
    • PlantUML Viewer
    • PlantUML language

Atomのパッケージのインストールはコマンドライン

apm install plantuml-viewer

apm install language-plantuml

としてやると楽です。

書き方

簡単なものであればPlantUML Cheat Sheet様が参考になります。

公式の解説はこちら

例えばこんな風に循環参照してしまっている箇所がビジュアル的に見て取れたりします。素晴らしい! f:id:AkiIro:20160924025928p:plain

まとめ(意気込み)

UMLを使って綺麗なアーキテクチャをつくろう!

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);
    }
//以下適当なコード
}

ちなみにアタッチするとこんな感じになります。

f:id:AkiIro:20160916034112p:plain

[SerializeField]や[HideInspector]について

アトリビュート全般に関してはテラシュールブログ様がとてもわかりやすい記事をくださっています。 ここで重要なのは

  • [SerializeField]でメンバはシリアライズできる
  • [HideInspector]でメンバはインスペクタ上からは見えなくなる

以上の二点です。

void Reset()について

公式のリファレンスに素晴らしく簡潔にわかりやすく記述してくださっています。 ここで重要なのは

  • void Reset()はエディタ上でスクリプトをオブジェクトにアタッチした際に呼ばれる。

という一点です。

Assertについて

void Awake()内にAssertを書くことで、万が一うまくシリアライズできていない場合にエラーを出してわかるようにしておきます。 Assertは引数がfalseになるとエラーを出してくれて、かつリリース時にはコンパイルされません。(つまりデバッグ中だけ動作する。)

応用について

これを応用して簡易的に事前に計算できるものは事前に計算したりすることが可能です。

とても初歩的かつ地味な内容でしたが、お読みいただきありがとうございました。