Unityを使ってシェーダーを作る方法を学ぶ連載。今回はサーフェースシェーダーのリムライティングを扱う。
Unityを使ってシェーダーを作る方法を学ぶ連載「Unityで始めるシェーダー入門」。連載第1回ではシェーダーの概要と作り始めるまでの環境構築を紹介した。
今回はサーフェースシェーダーのリムライティングについて解説する。今回紹介する「リムライティング」とは、3Dモデルの輪郭が強調されて中心が半透明な、ガラスのような感じになるシェーダーだ。先に、シェーダーを適用した結果を図1に示しておこう。
連載第1回でインポートしておいた、「Ethan」というキャラクターの3DモデルをScene画面上に2体配置しておこう。カメラの位置やEthanの位置を調整して図2のように配置しておく。
まず、連載第1回で作成した「Shaders」フォルダを選択して、マウスの右クリックで表示されるメニューから「Create」→「Shader」→「Standard Surface Shader」と選択する。新しく作成されたShaderには「RimlightingShader」と名付けておこう。
次に、同じく第1回で作成した「Materials」フォルダを選択して、マウスの右クリックで表示されるメニューから「Create」→「Material」と選択する。新しく作成されたマテリアルには「RimlightingMaterial」と名付けておこう。
RimlightingShaderの中身は、連載第4回までの通り、Standard Surface Shaderのコードが記述されている。このコードをリスト1のように変更する。
Shader "Custom/RimlightingShader" { Properties{ _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo (RGB)", 2D) = "white" {} _DotProduct("Rim effect", Range(-1,1)) = 0.25 } SubShader{ Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" } LOD 200 Cull Off CGPROGRAM #pragma surface surf Lambert alpha:fade sampler2D _MainTex; fixed4 _Color; float _DotProduct; struct Input { float2 uv_MainTex; float3 worldNormal; float3 viewDir; }; void surf(Input IN, inout SurfaceOutput o) { float4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; float border = 1 - (abs(dot(IN.viewDir, IN.worldNormal))); float alpha = (border * (1 - _DotProduct) + _DotProduct); o.Alpha = c.a * alpha; } ENDCG } FallBack "Diffuse" }
2〜6行目のPropertiesの中で、Inspector内に表示させる項目名と型を宣言している。
5行目はプロパティ変数名が「_DotProduct」で、インスペクターに表示するのが「Rim effect」という項目名で、変数の型には「Range」を使用して範囲制限付きのスライダーを表示することを意味する。規定値は「0.25」としておく。
13行目では、使用するオブジェクトの種類に応じて、その裏面が表示されるようにすることができる。このような場合は、モデルの背面が削除(カリング)されないように「Cull Off」を追加する。
16行目では、非常に手軽なランバート反射率を使用している。さらに「alpha:fade」を用いた透明シェーダーを「Cg」に送る。
21〜25行目のInput構造体では、Unityが現在のビュー方向とワールド法線方向を入力するように、入力構造を変更するための、各変数名の定義を行っている。
今回のシェーダーはオブジェクトのシルエットのみを表示することで機能する。オブジェクトを別の角度から見ると、その輪郭が変わる。幾何学的に言えば、モデルのエッジは、法線方向が現在のビュー方向に対して直交(90度)である全ての三角形だ。
Input構造体では、それぞれworldNormal(オブジェクトの法線ベクトル)とviewDir(視線ベクトル)というパラメーターを宣言している。
2つのベクトルが直交するときの問題は、dot関数で「視線ベクトル」と「法線ベクトル」との内積を使用して解くことができる(29〜30行目)。この辺りは、ちょっと難しいので、このシェーダーをScene上に配置したSphere(球体)に適用させて、実際にどのように表示されるかを見てみよう。図3のように表示される。
図3を見ると分かるが、Sphereの輪郭部分は透明度が低く、中央部分は透明度が高くなっている。輪郭部分では視線ベクトル(カメラから見た位置)と法線ベクトルが垂直近い角度で交わるが、中央部分では並行に近い角度で交わる。
このベクトルが交わる角度を透明にすればいい。そのためには、29行目で、内積の値を取得し、垂直に交わる場合は透明度を1、並行の場合は透明度を0にするために、絶対値(abs)を取って1から差し引いている。よって、垂直に交わる場合は1、並行に交わる場合は0となる。この値を変数borderに代入している。平行に交わる中心部分が透明化されていくわけだ。
31行目では、最終的な見栄えを決定するために、テクスチャの元のalphaに新たに計算された係数を掛けてAlphaに指定している。
MaterialsフォルダにあるRimlightningMaterialを選択してInspectorを表示させると、図4のように表示される。Colorには水色を選択。Rim Effectのスライダーを動かすと、中央部分の透明度が変化する。
このマテリアルを図2の2体の3Dモデルにドラッグ&ドロップする。すると図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.