LoginSignup
12
9

More than 5 years have passed since last update.

UnityのRealtimeGIを試してみる(Emissionのオンオフをしよう)

Last updated at Posted at 2019-03-15

はじめに

こんにちは、ここ数週間めっきり記事を書かなくなってしまいました。ちょっとゲーム作るの楽しくなっちゃって…

最近作っているVRコンテンツで、なんとなくリアリティを追求しようという気持ちになりまして、ライティングとか立体音響とかを触っています。
今回はその際に用いたライティング技術の一つである、GI(GlobalIllumination)を触ってみようという記事を書こうと思います。

どんなものが出来るの?

4d616dda72f79ab95a5731438bb0f190.gif
前方にあるのは鏡です。パイプの光の色が壁面に反射していることがわかりますね。エモい。
こういうのができます。反射光とPostProcessingStackのBloomはUnityライティングの花形感があります。実装だけならお手軽ですしね。

実装

GlobalIlluminationってなんぞや

GlobalIllumination(以下GI)とは、レンダリング技法のひとつで、日本語で言うと「大域照明」となります。古典的なレイトレーシングである局所照明に比べると、ある物体の反射光が間接的に他のオブジェクトを着色する様子や屈折によって光が一部分に集合し、そこだけ明るくなるコースティクスといった現象の表現が得意なようです。
Wikipediaの記事
UnityにはEnlightenというGIのミドルウェアが統合されており、これのおかげでGIによるレンダリングが出来るみたいです。
GIの照度マップはオブジェクト毎にベイクされているようで、Emissionの設定によってはランタイムで光源の色や強さを変えることができるようです(上記のgif参照)。これを使えばエモライティングが出来そう…?

GIを実装してみよう

御託はいいからって感じですかね。試しにGIの威力を見てみましょう。
真面目で勤勉な皆様のためにここにいつもの「レイトレーシングしないと出られない部屋」をご用意いたしました。
キャプチャ281.PNG
各オブジェクトのMeshRendererのプロパティである、LightmapStaticをオンにします。
キャプチャ280.PNG
ツールバーのWindow -> Rendering -> LightSettingでライティング画面を出します。環境光の効果を除くためにEnvironmentの項目のIntensity Multiplierの値を0にしましょう。オブジェクトが真っ暗になってしまうでしょうが大丈夫です。
コレでよし。Emissionする設定にしたmaterial(ただしEmissionの設定がBakedではなくRealtimeになっていることを確認しましょう)を貼り付けた球でも置いてみましょう。Emissionマテリアルを貼り付けた球についてもLightmapStaticを忘れないように。
キャプチャ282.PNG
こんな感じになりました。雰囲気有りますね~~ただコレにも問題があって、リアルタイムにisActiveの値をいじったりすると反射光だけ残ってしまいます。
5bf9cbc70541ce34d105fc660f9db631.gif

違和違和違和♥(ちゃんと照度マップを反映しないと)ダメだぞぉ♥
照度マップの特性の調整を反映するには renderer.UpdateGIMaterials() を使います。

GITest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GITest : MonoBehaviour {
    public Renderer targetRenderer;
    // Use this for initialization
    void Start () {
        targetRenderer = GetComponent<MeshRenderer>();
    }

    // Update is called once per frame
    void Update () {

    }
    public void OnEnable()
    {
        Debug.Log("Enabled GI");
        targetRenderer.material.EnableKeyword("_EMISSION");
        targetRenderer.UpdateGIMaterials();
    }
    public void OnDisable()
    {
        Debug.Log("Disabled GI");
        targetRenderer.material.DisableKeyword("_EMISSION");
        targetRenderer.UpdateGIMaterials();
    }
}

例えば上記のスクリプトをアタッチすればemissionをactiveと同時に操作したうえでGIを更新していい感じになります。
98e2471e8d96d41444466a18ffe43ed1.gif

うむ。

リアルタイムに光源の特性を変更してみよう

色々変更した上で先述の renderer.UpdateGIMaterials() を使えばリアルタイムに光源の特徴を変更できます。

色を変えよう

2e2f51090ebe795d858b31d4ea97b266.gif
GIでは色は照度マップの形状自体には影響を及ぼさないので色を変えてもいい感じのライティングを維持することができます。color自体にEmissionのIntensityは含まれていません。colorに乗算する値がIntensityとなるようです。

    public void ChangeColor(Color newColor)
    {   
        color = newColor;
        targetRenderer.material.SetColor("_EmissionColor", color * intensity);
        targetRenderer.UpdateGIMaterials();
    }

強さを変えよう

54b1e18261ba4b72c9dcb03fcab5d0fe.gif

Intensityも同じように照度マップの形状に影響を与えないので変更してもいい感じのライティングを保つことができます。上記と同様のコードで

    public void ChangeIntensity(float newIntensity)
    {   
        intensity = newIntensity;
        targetRenderer.material.SetColor("_EmissionColor", color * intensity);
        targetRenderer.UpdateGIMaterials();
    }

とすれば明るさを変更したうえでGIレンダリングの様子を更新することができます。

最後に(RealtimeGIは万能なのか?)

ここまで結構ランタイムでも光源を変化させられる例をお見せしてきました。結局このRealtimeGIは万能なのでしょうか?
もちろんそんなことはありません。LightmapStaticなので位置を変更できないのはもちろん、純粋にベイクされた光源に対して若干精度が悪い、照度マップ自体は事前にベイクされたものなのであまりにも初期状態とかけ離れた設定にするとおかしくなる、などの欠点があります。
確かに簡単に見た目を盛れるので魅力的ではありますが、用法用量を守ってお使いになるのが良いでしょう。

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9