シェーダーでオブジェクトをスライス(輪切り)表示させるにはUnityで始めるシェーダー入門(7)

Unityを使ってシェーダーを作る方法を学ぶ連載。今回はオブジェクトをスライス(輪切り)したような見栄えになるシェーダーを紹介する。

» 2018年05月17日 05時00分 公開
[薬師寺国安PROJECT KySS]

 Unityを使ってシェーダーを作る方法を学ぶ連載「Unityで始めるシェーダー入門」。連載第1回ではシェーダーの概要と作り始めるまでの環境構築を紹介した。

 今回はオブジェクトをスライス(輪切り)したような見栄えになるシェーダーを紹介する。Sphere(球体)と3Dキャラクターがスライスされた画像が図1だ。今回は、このような表示になるシェーダーを紹介する。

図1 Sphereと3Dキャラクターが輪切りにされている

 Hierarchyの「Create」→「3D Object」→「Sphere」と選択してSphereをScene画面上に配置する。同じく、これまでの連載でインポートしておいた、「Ethan」の3DキャラクターをScene画面上に1体配置しておこう。カメラの位置やSphereや3Dキャラクターの位置を調整して図2のような表示にしておく。

図2 Scene画面上にSphereとEthanを1体配置した。Game画面の確認もできる

スライス表示を実装するシェーダー

 新しいScene画面を開き、「Shaders」フォルダを選択して、マウスの右クリックで表示されるメニューから「Create」→「Shader」→「Standard Surface Shader」と選択する。新しく作成されたShaderには「SliceShader」と名前を付けておこう。

 次に、「Materials」フォルダを選択して、マウスの右クリックで表示されるメニューから「Create」→「Material」と選択する。新しく作成されたMaterialには「SliceMaterial」と名前を付けておこう。

 先ほど作成した、Materialsフォルダにある、SliceMaterialを選択して、Inspectorを表示させてみよう。Shaderの位置に先ほど作成したSliceShaderが「Custom/SliceShader」として関連付けられている。通常は、Standard Surface Shaderとして作成したシェーダーは「Custom」というグループ名付きで表示される。

 SliceShaderの中身は、これまでの連載通り、Standard Surface Shaderのコードが記述されている。このコードをリスト1のように変更する。

Shader "Custom/SliceShader" {
    Properties {
        _Color("Color",Color) = (1.0,1.0,1.0,1.0)
    }
    SubShader {
        Tags {"RenderType"="Opaque"}
        Cull off
        
        CGPROGRAM
        #pragma surface surf Lambert
 
        struct Input {
            float3 worldPos;
        };
 
           float4 _Color;
 
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = _Color;
            clip(frac(IN.worldPos.y * 15) - 0.5);
        }
        ENDCG
    }
    FallBack "Diffuse"
}
リスト1 SliceShaderのコード

 コードの解説については、今までの連載で解説したコードについては省略しているので、ご了承願いたい。

 ここで使用しているサーフェースシェーダーのInput構造体には、下記のURLで使用されている値(「worldPos」「worldRefl」など)を使用している。

 12〜14行目のInput構造体の中で、float3型のworldPos変数を定義している。これによって、オブジェクトの位置であるワールド座標の位置が取得できる。

 18〜21行目のsurf関数では、リスト2のように記述している。

void surf (Input IN, inout SurfaceOutput o) {
    o.Albedo = _Color;
    clip(frac(IN.worldPos.y * 15) - 0.5);
}
リスト2 surf関数

 リスト1の20行目では、「IN.worldPos.y*15」でワールド座標に15を乗算し、frac関数では引数に指定された値の小数部(10進数値)を取得する。つまり、0以上1未満の値を返す。それから0.5をマイナスすることで、「-0.5」から「0.5」を繰り返すことになる。clip関数では、与えられた引数が「0」より小さい場合は描画を行わない。「0」以上で描画を行う。これを利用してマスク処理を行うことで、縦に輪切りされたような模様が作成される。

 「IN.worldPos.y*15」の「15」の値を変更することで、縞模様の幅を変更できる。値を小さくすれば縞模様の幅が大きくなる。

実行結果

 MaterialsフォルダにあるSliceMaterialを選択してInspectorを表示させると、図3のように表示される。Colorに青色を選択するだけだ。スライスはシェーダーの中で自動的に行われる。

図3 SliceMaterialのInspector

 図3のColorの指定によってSliceMaterialは図4のような表示になる。

図4 作成されたSliceMaterial

 この図4のマテリアルをScene画面上に配置した、Sphereと3Dキャラクターの上にドラッグ&ドロップする。すると、図5のように輪切りにされたような縞模様で表示される。

図5 輪切りにされたような縞模様で表示された

いろいろと値を変えて試してみよう

 今回はこれで終わりだ。今回のコードは今までの連載でやってきたコードが出てきているので、surf関数以外は十分に理解できたのではないかと思う。今回の肝は、このsurf関数内の処理になる。

 「clip関数では、与えられた引数が0より小さい場合は、描画を行わない」と解説をしておいたが、0.5をマイナスしなかった場合はどうなるかというと、輪切りにはならず、縞模様は表示されない。要するに、スライス表示は行われずに描画が完全に行われてしまうわけだ。オブジェクトが青色のままで完全に表示される。

 では「-0.9」を指定すればどうなるかを試すと、縞模様は表示されるがごくわずかに表示されるだけだ(図6)。オブジェクトもほとんど消えかけて表示される。「1」を指定してしまうと、透明人間になって、3Dキャラクターのサングラスだけが表示される。「-0.1」を指定すると、縞模様の間隔が極端に狭く表示される。

図6 「-0.5」の数値の代わりに「-0.9」を指定した

 よって「-0.5」と指定するのがちょうどいい表示になるわけだ。どのような処理になるか分からない場合は、そこに指定されている値をいろいろ変化させて試してみると、理解ができるようになる。各自がいろいろ試してみてほしい。

次回は、鏡面反射(オブジェクトのガラス化)について

 次回は、鏡面反射(オブジェクトのガラス化)について解説するので、お楽しみに。

参考書籍

著者プロフィール

薬師寺 国安(やくしじ くにやす) / 薬師寺国安事務所

薬師寺国安事務所代表。Visual Basicプログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。

1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。

1997年に薬師寺聖とコラボレーション・ユニット「PROJECT KySS」を結成。

2003年よりフリーになり、PROJECT KySSの活動に本格的に参加。.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。

Windows Phoneアプリ開発を経て、現在はWindowsストアアプリを多数公開中。

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。

Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。

Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。

Microsoft MVP for Development Platforms-Windows Platform Development(Oct 2014-Sep 2015)。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。