読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】とあるライトマップと光沢感(スペキュラー)

3D おもしろ演出、演出の強化 Unity5.6 Unity Lightmap

Unityユーザー助け合い所で少し気になった投稿があったので、調査してみました。

Lightmapを焼くと光沢が出ない

f:id:tsubaki_t1:20170304214320j:plain

ライトマップを使用する時、事前に光の情報をライトプローブに格納しておく事で、ダイナミックなオブジェクトに対して間接光や直接光の影響を与える事が可能です。

但し、Lightprobeにはライトの位置は格納されていないため、光沢といった表現は表示出来ないみたいです。

 

ちなみにStaticの場合はDirectional Specularの設定をONにしておくことで、スペキュラー情報も含めてライトマップにベイクしてくれます。ただ、間接光からの反射も光沢と認めるのか、直接光が無くても何故か光沢が表現されると、微妙に過剰に表現されてる節があります。

…なおDirectional Specularの機能は5.6から無くなります。

光沢を表現したい

個人的な考えでは、余りゲームに詳しくない人は「光沢の有無」でゲームのグラフィッククォリティを認識してる節があるので、やはり光沢は欲しいです。ので、光沢を表現する方法を考えてみます。

Directional Lightの場合

Directional Lightを使用している場合はMixedを使用する事で解決しますが、Spot LightやPoint Lightのような計算が面倒なライトの場合、ライトの範囲内でも光沢が出なかったりします。

f:id:tsubaki_t1:20170304215041j:plain

PointLightやSpot Light

Point LightやSpot Lightでリアルタイムに光沢を表現したい場合、リアルタイムなライトが欲しいので、ポイントライトを、スタティックなライトと同じ位置に用意します。

f:id:tsubaki_t1:20170304220308j:plain

BakedはBounce Intensityは自由に設定出来ますが、RealtimeはPrecomputed Realtime GIがOFFならばBounce Intensityは0です。

ここで、Lighting>LightprobesのAdd Direct Lightのチェックも外しておきます。そうすると、Lightprobeには間接光からの光のみが反映されるようになるので、二重に光の影響を受ける事を防げます。

ただし、LightのCulling Mask動的に動くオブジェクトだけを指定しないと、今度はstaticの方が輝度が高くなります。場合によっては、Add Direct Lightのチェックを入れつつ、直接光と間接光を半々くらいにするのも良いアイディアかもしれません。

f:id:tsubaki_t1:20170304221239j:plain

最終的には、こんな感じになります。

f:id:tsubaki_t1:20170304225850j:plain

それとReflection Probeを使わないと、なんちゃって光沢付きモデルを表現した何かになるので、Reflection Probeは積極的に使うと良いかと。

Pixel Light Countの限界

今回紹介しているアプローチでは、Pixel Light Countの数によっては妙な挙動になる事があります。
Pixel Light Countはピクセルライトを使用できる制限で、その数以上のライトは頂点カラーベースのライティングに切り替わります。また、同一のオブジェクトが受けるスペキュラーの数も制限するらしく、下のように複数のライトから単一のオブジェクトを照らしている場合、優先度の高いライトの光沢が表現されます。

f:id:tsubaki_t1:20170304222905j:plain

そのため、この手法では「Point Lightの範囲を被らないように設定する」事が必要になりそうです。範囲がかぶらなければ(モデル一つに対して複数のライトが影響しないのであれば)、Pixel Point Lightが1でも下のように光沢がライト毎に出てます。

f:id:tsubaki_t1:20170304223731j:plain

ライトの優先度は輝度や距離等、様々です。優先順位戦争で負けたポイントライトは、頂点カラーに流し込まれます。

f:id:tsubaki_t1:20170304225200j:plain

なお、Render ModeでImportantを選択すると単一のオブジェクトに複数のスペキュラを指定出来るようになりますが、重くなるんじゃないかなと予想してます。

f:id:tsubaki_t1:20170304225646j:plain

AreaLightやEmissive Objectの場合

Emissiveなマテリアルを持つオブジェクトの場合、ReflectionProbeを用意するとスペキュラーちっくな表現が可能です。

その際、ReflectionProbeのHDRはON、かつEmissiveなオブジェクトがReflectionProbeに映る必要があります。

f:id:tsubaki_t1:20170307102420j:plain

f:id:tsubaki_t1:20170307104057j:plain

f:id:tsubaki_t1:20170307102850g:plain

AreaLightは光沢表現を与える物が無いので光沢が表現されません。

ので、強引ですが光沢用の追加ライトを追加します。もしくはAreaLightと同じ大きさのEmissiveなオブジェクトを用意し、ReflectionProbeに写します。

f:id:tsubaki_t1:20170304234655j:plain

モバイルでは…

個人的には、Matcapのような「決め打ちで光沢が表現されてるもの」や、専用のシェーダーを用意するのが一番クォリティ高く見えるんじゃないかなって気がしています。

tsubakit1.hateblo.jp

docs.unity3d.com

また、Lightprobeで頑張るよりも環境マップで決め打ちで光の反射を与えてしまうのも手かもしれません。

5.6以降では

Shadow Maskを使うのが良さそうです。

mixedを指定してやれば、特に何らかの設定を行わなくとも下のような表現になります。

また、事前に準備した影とリアルタイムに準備した影の境目がわかりづらく、かつスペキュラ等もちゃんと表現されています。 …すきかも

f:id:tsubaki_t1:20170304231829j:plain

tsubakit1.hateblo.jp

なお、5.6では加算ロード時に「Depth OnlyやDon't Clearを指定したカメラ」が「CameraのDepthの一番奥」にある場合、毎フレーム「GL.End requires material.SetPass before!」のようなエラーが出るみたいです。

f:id:tsubaki_t1:20170304233415j:plain

一応既にFixedになっているので、その内治るんじゃないかなと予想してます。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

 
 

【Unity】Timelineエディタのプレビューリリース版その1がリリース

3D Unity5.6 Unity Beta

f:id:tsubaki_t1:20170208224608p:plain

UnityのTimelineエディタのプレビューリリース版その1がリリースされてました。

Timeline Experimental Preview Release 1

https://forum.unity3d.com/threads/timeline-experimental-preview-release-1.455265/

機能

現状の機能は大雑把にこんな感じです。

  • タイムラインでアニメーションを制御する
    アニメーションをタイムラインに仕込んだり出来るし、ブレンドも可能
  • タイムライン上でオーディオを制御出来る
  • タイムライン上でスクリプトを制御出来る
    イベントのような瞬間的な物だけではなく、タイムラインで指定した期間連続して駆動するものも表現出来る
  • アセットベースでありながら、シーンのオブジェクトに紐付け出来る仕組み*1

www.youtube.com

 補足

なお、

  • Unityバージョン間でプロジェクトの下位互換性は保証されません。特にExperimentalなプロジェクトを開く場合、プロジェクトをアップグレードする前に、バックアップする事を強くお薦めします。
  • プレビュー版にはビルド機能は含まれません。
  • バージョンによってAPIが変わったり削除されたりします。

また、見てる感じ、明らかにApplyRootMotoinのような仕組みで移動する事が前提になっているように見えます。うーん

関連

tsubakit1.hateblo.jp

*1:無駄に複雑

【Unity】複数のColliderを結合するComposite Collider 2Dを使って少し遊ぶ

2D Unity Unity5.6

今回はUnity 5.6に追加されたComposite Collider 2Dについてです。

Compound Collidersという機能

Rigidbodyの下にColliderが複数ある時、実はUnityはColliderを一つにまとめて処理してくれます。これで動かす場合、MeshColliderよりも高速で動作します。

f:id:tsubaki_t1:20170222002439g:plain

こういったCompound(複合)コライダーはMeshColliderやPolygonColliderより大体高速で動作し、かつMeshCollider系の制約も殆ど受けないので色々と便利です。

 

例えば、下にMeshColliderとComposite Colliderで作成したモデルを用意してみます。

当たり判定は大体同じように作れますが、MeshColliderはCompositeColliderと比較して、単純に当たり判定の計算負荷が高くアニメーションに非対応*1、かつMeshCollider同士の当たり判定が出来ない問題があります。

そのため、単純な形状のコライダーを動かして当たり判定を作るCompoundColliderという機能があります。

f:id:tsubaki_t1:20170222221956j:plain

ちなみに、CompoundColliderはAColliderBuilderでサクっと作れます。

f:id:tsubaki_t1:20170222225404j:plain

https://www.assetstore.unity3d.com/jp/#!/content/15058

CompositeCollider2Dという機能

さて、5.6でCompoundColliderに微妙に似てますが異なる機能が追加されました。CompositeColliderなるコンポーネントです。

これは複数のCollider2D(MeshColliderとBoxColliderのような頂点ベースのコライダー)を結合し、一つのコライダーに変換する機能みたいです。

 

例えば下のように、複数のBoxColliderが同じ範囲に入ると、一つのColliderのように結合されているのが分かります。

f:id:tsubaki_t1:20170222222833g:plain

Colliderの結合は、同期(動かした時に計算?)、非同期、スクリプトからのアクセスの3タイプがあります。要するに、このメッシュ結合はランタイムで動きます。

f:id:tsubaki_t1:20170222223254j:plain

ちなみに結合コストは結構高いのか、弾幕を作り「一つのRigidbody + 一つのComposite Collider(内部に500個程のCollider)」をやってみた所、バラバラに動かしたほうが早かったです。

また、Geometry typeをOutlineに設定すると、コライダーの形状に沿ってコライダーを作成するみたいです。

f:id:tsubaki_t1:20170222223754j:plain

ダイナミック洞窟生成

この機能で思いついたのが、ダイナミック洞窟生成です。

やってる事は物凄い単純で、Geometry TypeをOutlineに設定し、あとはモノをどんどん増やしていくだけです。

下のようになります。

作り方

  1. 結合するCollider2Dの付いたGameObjectを用意する
  2. CompositeCollider2Dの付いたGameObjectを用意する
  3. 1を2の子オブジェクトとして配置
  4. 1のColliderのUse By Compositeにチェックを入れる

f:id:tsubaki_t1:20170222224642g:plain

 

後はEdge Radiusの値を調整します。小さすぎると当たり判定が貫通する事がありますし、大きすぎると凄い浮きます。

f:id:tsubaki_t1:20170222225021j:plain

後はComposite ColliderにはRigidbodyが付いてくるので、BodyTypeをStaticもしくはkinematicに設定しておきます。

f:id:tsubaki_t1:20170222225605j:plain

なんか、コレだけで何かゲームを作れそうな気がしなくもないですね。穴掘りゲーム的な。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

*1:メッシュを作成しMeshBake等でメッシュ情報を更新しなければ当たり判定が付いてこない

【Unity】Area Lightと、Emissiveな材質を持つ発光するオブジェクトが輝けと囁く

3D Unity Unity5.6 Lightmap ステージ構築

Unityのライティングシステムの隅にひっそりと存在するArea Light(エリアライト)、その知られざる生態系について、今回は踏み込んでみようと思います。

影の表現が柔らかくなるAreaLight

AreaLightですが、マニュアルを見ても「ライトが柔らかくなる」的な事しか書いていません。

リアライトは複数の異なる方向から同時にオブジェクトを照らすので、他の種類のライトと比べてシェーディングが柔らかく繊細になります。

 細かい事は置いておいて、実際にAreaLightとDirectional Lightを比較すると、確かに影がかなり柔らかくなっています。左がAreaLight、右がDirectional Lightです。
Directional Lightはハッキリ輪郭が見えるのに対し、AreaLightは濃淡はハッキリしていますが輪郭はボヤけて見えます。

f:id:tsubaki_t1:20170206230834j:plain

広い範囲からの照射ばぼんやり、狭い範囲からの照射はハッキリ

Area Lightの挙動は2パターンのライト画像を比較すると、何となく想像が出来ます。

下にAreaLightの横幅が狭い物と広い物を用意して比較しました。狭いAreaLightは影の濃淡がハッキリと見えていますが、広いAreaLightは全体的に薄く広く広がっています。

f:id:tsubaki_t1:20170206231424j:plain

f:id:tsubaki_t1:20170206231428j:plain

実際の実装は分かりませんが、挙動としては多分こんな感じです。

AreaLightは複数の異なる方向から対象のオブジェクトを照らして、ふんわりと柔らかい影を表現してるんじゃないかなと思います。

f:id:tsubaki_t1:20170206233417j:plain

ちなみに現実も、空も光は太陽から直で来る訳ではなく大気である程度拡散してから降り注ぐ感じになると思います。それは正しいか?もっと詳しく?そんなこと俺が知るか!

AreaLightの影は静的なオブジェクトに焼く

ふわっと優しくなるAeraLightは、残念ながらリアルタイムに影を表現する事が出来ません。基本的に静的なオブジェクトに焼き、ライトマップを使用する感じで利用します。

基本的な光表現はLightProbeでダイナミックなオブジェクトに受け渡します。また、ScreenSpaceAmbientOcclusion等でAO表現や古き良き丸影を使うと、意外と馴染んで見えたりします。

f:id:tsubaki_t1:20170206235516j:plain

発光するEmissiveオブジェクト

AreaLightと似たような性質を持つ機能として、Emissiveな属性を持つマテリアル(材質)を持つオブジェクトという物があります。

例えばStandardAssetsの場合、Emissiveが設定されていて、かつLightmapのstaticが入ったオブジェクトであれば、発光します。

f:id:tsubaki_t1:20170206235902j:plain

f:id:tsubaki_t1:20170207000055j:plain

Emissiveの特性

EmissiveなオブジェクトはAreaLightと異なり、GIモードがRealtimeモードならばランタイム時に光の強度や色を変更する事が出来ます。

ただ、基本的にEnlitenのRealtime GI Resolutionベースで光源を設定しているので、Realtimeモードの場合はAreaLightと比較して光の表現が雑です。

f:id:tsubaki_t1:20170207000508g:plain

AreaLightと似たような特性

雑ではありますが、AreaLightと同様に広い範囲から照射すればフワッとした、狭い範囲から照射すれば割とハッキリとした影が表現されます。

また静的(static)なオブジェクトにしか影や光源が反映しないのも同様です。基本的に動的に動かすオブジェクトに影響を与えたい場合、Lightprobe様が大活躍します。

f:id:tsubaki_t1:20170207000916j:plain

また、マテリアルのGIモードをBakedに設定し、Final Gatherを設定すると、AreaLightと比較して殆ど見分けがつかないレベルの光が表現出来ます。

発光する範囲と形状

Emissiveなオブジェクトの優位性の一つは、テクスチャでマスクを設定したり、複雑な範囲は形状から発光出来る点です。

Emissiveな項目にテクスチャを設定すると、光が漏れないようにマスクを掛けたり、光の色にフィルターをかけるような表現が出来ます。

f:id:tsubaki_t1:20170207001837j:plain

また、マテリアル単位で光るので、複雑な…例えば蛍光灯やネオンのような表現も出来たりします。Arealightは基本的に四角で表現するので、複雑な形状を表現したい場合には若干有利です。

f:id:tsubaki_t1:20170207002727j:plain

で、どっちが良いの?

個人的にはEmissiveなオブジェクトの方が使いやすいといえば使いやすいです。

ただしRealtimeGIベースは表現が割と汚くなりやすく、しかしてBaked&FinalGatherを使用するとライトを焼くのに猛烈に時間がかかるので、その辺りがネックになります。

個人的な使い分けとしては、広範囲にやるならAreaLight、蛍光灯等の細かいパーツならEmissiveオブジェクト、輝度があまり高くなくうっすらと光る程度ならEmissiveといった感じです。

ちなみにUnity 5.6b6にProgressive Lightmapperという、「任意の範囲を優先して焼く&EmissiveをRealtimeGIベースじゃなくす」機能を持ったライティングモードが追加されるので、ある意味Emissiveの問題は回避は出来るといえば出来るようになるかもしれません。

f:id:tsubaki_t1:20170207003705g:plain

シーンビューで見てる位置を優先して、粗いライティングから収束していく感じでライトを焼いてくれます。広いマップでも見てる範囲を優先して焼いてくれるので、確認したい範囲をサクサクっと確認出来て便利

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp