このページでは、サーフェスシェーダーのカスタムサーフェスシェーダーのライティングモデルの例を紹介します。もっと一般的なサーフェスシェーダーについては、サーフェスシェーダーの例を参照してください。
デファードライティング はカスタマイズされたマテリアルライティングモデルではうまく機能しない場合もあるため、以下の例のほとんどは、シェーダーを フォワードレンダリング のみにコンパイルしています。
以下は、ビルトインの Lambert ライティングモデルを使用するシェーダーです。
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
これは、シーンにディレクショナルライトが 1つあるとき、テクスチャがある場合とない場合の見え方の違いです。
以下の例は、ビルトインの Lambert モデルを使用する代わりに、カスタマイズしたライティングモデルを作成して同じ効果を得る方法を示しています。
これを行うには、多くのサーフェスシェーダーライティングモデル関数の使用が必用です。ここに簡易な Lambert ライティングモデルがあります。CGPROGRAM
セクションだけが変わっていることに注目してください。周囲のシェーダーコードはまったく変更されていません。
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf SimpleLambert
half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten);
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
この簡易なディフューズライティングモデルでは、LightingSimpleLambert
関数が使われています。LightingSimpleLambert
関数は表面法線と光方向間のドット積を行うことでライティングを計算し、光の軽減や色を適用します。
以下は、 ラップされたディフューズ です。照明がオブジェクトの端を「包み込む」ような ディフューズ ライティングの変形です。表面下の散乱効果をシミュレーションするのに便利です。CGPROGRAM
セクションだけが変更されています。ここでも、周囲のシェーダーコードは同じなので省きます。
...ShaderLab code...
CGPROGRAM
#pragma surface surf WrapLambert
half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half diff = NdotL * 0.5 + 0.5;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten);
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...
これは、シーンにディレクショナルライトが 1つあるとき、テクスチャがある場合とない場合の見え方の違いです。
以下の例は、テクスチャのランプを使用して表面が光と法線間の角度にどのように反応するかを決定する “Ramp” ライティングモデルを表示しています。これは、さまざまなエフェクトに使用され、特に トゥーン ライティングとともに使用すると効果的です。
...ShaderLab code...
CGPROGRAM
#pragma surface surf Ramp
sampler2D _Ramp;
half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half diff = NdotL * 0.5 + 0.5;
half3 ramp = tex2D (_Ramp, float2(diff)).rgb;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * ramp * atten;
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...
これは、シーンにディレクショナルライトが 1つあるとき、テクスチャがある場合とない場合の見え方の違いです。
以下の例は、ビルトインの BlinnPhong ライティングモデルに似た簡単なスペキュラーモデルを示しています。
...ShaderLab code...
CGPROGRAM
#pragma surface surf SimpleSpecular
half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
half3 h = normalize (lightDir + viewDir);
half diff = max (0, dot (s.Normal, lightDir));
float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, 48.0);
half4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * atten;
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...
これは、シーンにディレクショナルライトが 1つあるとき、テクスチャがある場合とない場合の見え方の違いです。
Unity のビルトイン GI を模倣したシェーダーから紹介します。
Shader "Example/CustomGI_ToneMapped" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf StandardDefaultGI
#include "UnityPBSLighting.cginc"
sampler2D _MainTex;
inline half4 LightingStandardDefaultGI(SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
{
return LightingStandard(s, viewDir, gi);
}
inline void LightingStandardDefaultGI_GI(
SurfaceOutputStandard s,
UnityGIInput data,
inout UnityGI gi)
{
LightingStandard_GI(s, data, gi);
}
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
}
ENDCG
}
FallBack "Diffuse"
}
次に、GI 上にトーンマッピングを追加します。
Shader "Example/CustomGI_ToneMapped" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Gain("Lightmap tone-mapping Gain", Float) = 1
_Knee("Lightmap tone-mapping Knee", Float) = 0.5
_Compress("Lightmap tone-mapping Compress", Float) = 0.33
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf StandardToneMappedGI
#include "UnityPBSLighting.cginc"
half _Gain;
half _Knee;
half _Compress;
sampler2D _MainTex;
inline half3 TonemapLight(half3 i) {
i *= _Gain;
return (i > _Knee) ? (((i - _Knee)*_Compress) + _Knee) : i;
}
inline half4 LightingStandardToneMappedGI(SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
{
return LightingStandard(s, viewDir, gi);
}
inline void LightingStandardToneMappedGI_GI(
SurfaceOutputStandard s,
UnityGIInput data,
inout UnityGI gi)
{
LightingStandard_GI(s, data, gi);
gi.light.color = TonemapLight(gi.light.color);
#ifdef DIRLIGHTMAP_SEPARATE
#ifdef LIGHTMAP_ON
gi.light2.color = TonemapLight(gi.light2.color);
#endif
#ifdef DYNAMICLIGHTMAP_ON
gi.light3.color = TonemapLight(gi.light3.color);
#endif
#endif
gi.indirect.diffuse = TonemapLight(gi.indirect.diffuse);
gi.indirect.specular = TonemapLight(gi.indirect.specular);
}
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
}
ENDCG
}
FallBack "Diffuse"
}
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.