Bigdra.Log

備忘録

球の中にシーンの景色を入れる

目次 [TOC]

はじめに

こういうのです.

見かけたことはあるけど作ったことはなかったので試してみました.

環境

Unity 2019.3.0f6

やってみる

球を見るシーンを用意

まずはSphereを置いておきます.


次に, シェーダーを作成します. Create>Shader>Unlit Shaderで作成されたファイルを開き, 元々書いてあったコードをすべて下のコードに置き換えて下さい. これはビルトインシェーダーのskybox/cubemapを一部変更したものです.(https://unity3d.com/jp/get-unity/download/archive)

Shader "Custom/Cubemap" {
Properties {
    _Tint ("Tint Color", Color) = (.5, .5, .5, 1.)
    [Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0
    _Rotation ("Rotation", Range(0, 360)) = 0
    [NoScaleOffset] _Tex ("Cubemap   (HDR)", Cube) = "grey" {}
}

SubShader {
    Tags { "Queue"="Transparent" "RenderType"="Transparent"}
    Cull Front ZWrite Off
    Blend SrcAlpha OneMinusSrcAlpha

    Pass {

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma target 2.0

        #include "UnityCG.cginc"

        samplerCUBE _Tex;
        half4 _Tex_HDR;
        half4 _Tint;
        half _Exposure;
        float _Rotation;

        float3 RotateAroundYInDegrees (float3 vertex, float degrees)
        {
            float alpha = degrees * UNITY_PI / 180.0;
            float sina, cosa;
            sincos(alpha, sina, cosa);
            float2x2 m = float2x2(cosa, -sina, sina, cosa);
            return float3(mul(m, vertex.xz), vertex.y).xzy;
        }

        struct appdata_t {
            float4 vertex : POSITION;
            UNITY_VERTEX_INPUT_INSTANCE_ID
        };

        struct v2f {
            float4 vertex : SV_POSITION;
            float3 texcoord : TEXCOORD0;
            UNITY_VERTEX_OUTPUT_STEREO
        };

        v2f vert (appdata_t v)
        {
            v2f o;
            UNITY_SETUP_INSTANCE_ID(v);
            UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
            float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation);
            o.vertex = UnityObjectToClipPos(rotated);
            o.texcoord = v.vertex.xyz;
            return o;
        }

        fixed4 frag (v2f i) : SV_Target
        {
            half4 tex = texCUBE (_Tex, i.texcoord);
            half3 c = DecodeHDR (tex, _Tex_HDR);
            c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb;
            c *= _Exposure;
            return half4(c, _Tint.a);
        }
        ENDCG
    }
}


Fallback Off

}

このシェーダーファイルを右クリックしてCreate>Materialで作成されたマテリアルをさっきのSphereにつけます.

このマテリアルのインスペクターにあるCubemapに置きたい景色のCubemap用のテクスチャを貼れば完了です.

Cubemap用のテクスチャを用意

球に入れる適当なシーンを用意します. 今回はOculus Integrationのサンプルシーンを使いました.

次に, HierarchyでCreate>Light>Reflection ProbeでReflection Probeを作成し, シーンの中央らへんに配置します.

配置ができたら, Refelction ProbeのインスペクターでCubemapに映したいオブジェクトに応じてTypeを選択します.

Unity Documentation より

  • Baked プローブは、エディターでのベイキングによって生成される静的リフレクションキューブマップを保存します。
  • Custom プローブは、ベイクによって、または、ユーザーによる手動の設定によって、生成された静的キューブマップを保存します。
  • Realtime プローブはキューブマップをランタイムで更新するので、シーン内で動的オブジェクトに反応することができます。


staticなオブジェクトのみ対象とするか, 動的なオブジェクトも対象にするか, ランタイムに生成するかで選択するとよさそうです.
今回のシーンでは動くブロックなども含めたかったのでCustomでDynamic Objectsにチェックをいれて使いました.


次はReflection Probeの範囲の調整です.
Refelction Probeのインスペクターの一番上にあるEdit Bounding Volumeのアイコンをクリックするとこのような直方体が表示されます.

これがReflection Probeの範囲なので, Box SizeBox Offsetをいじって適切なサイズに調整します.

最終的にこんな感じにしました.

Cubemap capture settingsのResolutionなども好きなように設定して下さい.

諸々の設定が完了したらReflection Probeのインスペクターの一番下にあるBakeを実行すればCubemapのテクスチャが生成されます.
テクスチャの生成が完了したらRefelction Probeは消してもOKです(そのまま使いたい場合はもちろん残してもらっても大丈夫です.)

完成

最初に作ったシーンへ戻ります.

用意してあるマテリアルに生成したテクスチャを貼ります.

なんかぼやけてますね...
生成したテクスチャのインスペクターを見てみて下さい.

このようにMappingのConvolution TypeがSpecularだとぼやけるようなので, Noneに変更してApplyしてみて下さい.

すると, このようにきれいになりました!

参考

https://docs.unity3d.com/ja/2019.3/Manual/class-Cubemap.html https://docs.unity3d.com/ja/2018.4/Manual/class-ReflectionProbe.html https://light11.hatenadiary.com/entry/2018/07/10/231546