しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Unity で 3D モデルの表裏両面をレンダリングしたい

※ これは 2017/08/04 Blender ver.2.78c、Unity 2017.1f3 時点の情報です

最新版では動作が異なる可能性がありますのでご注意ください

前回は円筒に対してテクスチャを貼りこみやすい配置で UV 展開をしてみました

とりあえず、下記のような感じで円筒に貼りこむテクスチャを表裏2枚用意したので、Unity に取り込んで描画してみたいと思います

f:id:matatabi_ux:20170804210212p:plain

Blender から 3D モデルを Unity にもっていくために、おもむろに fbx ファイルとしてエクスポートします

f:id:matatabi_ux:20170804210802p:plain

[ファイル]-[エクスポート]-[fbx ファイル] を選ぶだけなのでかんたんです

Unity の Assets フォルダ直下に cylinder.fbx をエクスポートするとこんな感じで prefab ができるので、こちらを適当に Scene ビュー上にドラッグドロップで配置します

f:id:matatabi_ux:20170804211534p:plain

エクスポートしたモデルに設定されたマテリアルにはテクスチャ画像が張られていなかったので、先ほどの表と裏の画像も Unity のプロジェクト内にインポートします

f:id:matatabi_ux:20170804212211p:plain

とりあえず Assets 直下に cylinder-uv1.png と cylinder-uv2.png という名前で画像をインポート

次に表裏の画像をマテリアルに設定・・・と思ったら

f:id:matatabi_ux:20170804212740p:plain

表裏両面用のテクスチャを指定できる Shader がどうやら Unity には標準ではないらしく・・・Albedo の左の枠、表面テクスチャしか指定できません

裏面もテクスチャを描画したい!その場合はどうするかというと、Shader を自作すればよいようです

自作といっても1から全部作るのは面倒なので、Unity の標準 Shader をベースに改変して作成したいと思います

標準 Shader といっても普通に Unity をインストールしただけではソースコードは参照できないので、下記のページにて別途ダウンロードします

unity3d.com

f:id:matatabi_ux:20170804213537p:plain

ダウンロードのコンボボックスから「ビルトインシェーダー」を選ぶと標準 Shader のソースコードを含む zip ファイルをダウンロードできます

ダウンロードした zip ファイル内の DefaultResourcesExtraファルダ内に「Normal-Diffuse.shader」というファイルがあるはずなので、こちらを Unity プロジェクトの Assets フォルダ直下にコピーし、ファイル名を「DoubleSidesDiffuse.shader」に変更します

f:id:matatabi_ux:20170804223502p:plain

コピーした 「DoubleSidesDiffuse.shader」を Visual Studio で開いて下記のように編集・・・

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Custom/DobleSidesDiffuse" { // 名前変更
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Front (RGB)", 2D) = "white" {} // Base → Front に変更
    _BackMainTex("Back (RGB)", 2D) = "white" {} // _BackMainTex を追加
}
SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 200

    Cull Front // 裏面から描画

    CGPROGRAM
    #pragma surface surf Lambert

    sampler2D _BackMainTex; // _MainTex → _BackMainTex に変更
    fixed4 _Color;

    struct Input {
        float2 uv_BackMainTex; // _MainTex → _BackMainTex に変更
    };

    void surf (Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_BackMainTex, IN.uv_BackMainTex) * _Color; // _MainTex → _BackMainTex に変更
        o.Albedo = c.rgb;
        o.Alpha = c.a;
    }
    ENDCG

    Cull Back // 表面を描画(上記の CGPROGRAM から ENDCG を下記にコピーする

    CGPROGRAM
    #pragma surface surf Lambert

    sampler2D _MainTex;
    fixed4 _Color;

    struct Input {
        float2 uv_MainTex;
    };

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        o.Alpha = c.a;
    }
    ENDCG
}

Fallback "Legacy Shaders/VertexLit"
}

テクスチャを指定する Properties を増やして、表面だけの処理部分(CGPROGRAM から ENDCG の部分)をコピーして裏面用の描画も追加しました

Cull Front を指定すると裏面を描画し、Cull Back を指定すると表面を描画します

裏面の描画は MainTex となっていたところを BackMainTex に変更すれば描画するテクスチャを切り替えられるというわけ

これを保存して UnityEditor に戻ります

円筒のマテリアルの Sahder に Custom/DoubleSidesDiffuse を選択すると、テクスチャを指定できる箇所が増えたので Front に表面、Back に裏面用の画像を指定します

f:id:matatabi_ux:20170804224037p:plain

さてこれで Scene ビュー上の円筒を見てみると・・・

f:id:matatabi_ux:20170804224716g:plain

表裏で別のテクスチャが描画されていますね・・・Diffuse Shader は機能が少ないですが単に両面描画したいだけならこれで十分かも?