您的位置:首页 > 产品设计 > UI/UE

Surface Shaders 内置灯光模型(Build in lighting models)Lighting.cginc 和如何自定义灯光类型

2017-10-31 14:07 651 查看
//如果没有定义 LIGHTING_INCLUDED 的话 (这是"if not defined"的简写,是宏定义的一种,它是可以根据是否已经定义了一个变量来进行分支选择,)
#ifndef LIGHTING_INCLUDED
//使用 LIGHTING_INCLUDED
#define LIGHTING_INCLUDED
//引用 XXX
#include "UnityLightingCommon.cginc"
#include "UnityGBuffer.cginc"
#include "UnityGlobalIllumination.cginc"

//SurfaceOutput 结构体
struct SurfaceOutput {
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
};

#ifndef USING_DIRECTIONAL_LIGHT
#if defined (DIRECTIONAL_COOKIE) || defined (DIRECTIONAL)
#define USIN
4000
G_DIRECTIONAL_LIGHT
#endif
#endif

//如果 满足后面这些条件,执行 define (UNITY_LIGHT_FUNCTION_APPLY_INDIRECT)
#if defined(UNITY_SHOULD_SAMPLE_SH) || defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
#define UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
#endif

//声明 fixed4 UnityLambertLight
inline fixed4 UnityLambertLight (SurfaceOutput s, UnityLight light)
{
fixed diff = max (0, dot (s.Normal, light.dir));

fixed4 c;
c.rgb = s.Albedo * light.color * diff;
c.a = s.Alpha;
return c;
}

//声明 fixed4 LightingLambert
inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi)
{
fixed4 c;
c = UnityLambertLight (s, gi.light);

#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
c.rgb += s.Albedo * gi.indirect.diffuse;
#endif

return c;
}

//声明 half4 LightingLambert_Deferred
inline half4 LightingLambert_Deferred (SurfaceOutput s, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
UnityStandardData data;
data.diffuseColor   = s.Albedo;
data.occlusion      = 1;
data.specularColor  = 0;
data.smoothness     = 0;
data.normalWorld    = s.Normal;

UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2);

half4 emission = half4(s.Emission, 1);

#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
emission.rgb += s.Albedo * gi.indirect.diffuse;
#endif

return emission;
}

//声明无类型的一个函数 LightingLambert_GI
inline void LightingLambert_GI (
SurfaceOutput s,
UnityGIInput data,
inout UnityGI gi)
{
gi = UnityGlobalIllumination (data, 1.0, s.Normal);
}
//声明 LightingLambert_PrePass
inline fixed4 LightingLambert_PrePass (SurfaceOutput s, half4 light)
{
fixed4 c;
c.rgb = s.Albedo * light.rgb;
c.a = s.Alpha;
return c;
}

// NOTE: some intricacy in shader compiler on some GLES2.0 platforms (iOS) needs 'viewDir' & 'h'
// to be mediump instead of lowp, otherwise specular highlight becomes too bright.
inline fixed4 UnityBlinnPhongLight (SurfaceOutput s, half3 viewDir, UnityLight light)
{
half3 h = normalize (light.dir + viewDir);

fixed diff = max (0, dot (s.Normal, light.dir));

float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;

fixed4 c;
c.rgb = s.Albedo * light.color * diff + light.color * _SpecColor.rgb * spec;
c.a = s.Alpha;

return c;
}

inline fixed4 LightingBlinnPhong (SurfaceOutput s, half3 viewDir, UnityGI gi)
{
fixed4 c;
c = UnityBlinnPhongLight (s, viewDir, gi.light);

#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
c.rgb += s.Albedo * gi.indirect.diffuse;
#endif

return c;
}

inline half4 LightingBlinnPhong_Deferred (SurfaceOutput s, half3 viewDir, UnityGI gi, out half4 outGBuffer0, out half4 outGBuffer1, out half4 outGBuffer2)
{
UnityStandardData data;
data.diffuseColor   = s.Albedo;
data.occlusion      = 1;
// PI factor come from StandardBDRF (UnityStandardBRDF.cginc:351 for explanation)
data.specularColor  = _SpecColor.rgb * s.Gloss * (1/UNITY_PI);
data.smoothness     = s.Specular;
data.normalWorld    = s.Normal;

UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2);

half4 emission = half4(s.Emission, 1);

#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
emission.rgb += s.Albedo * gi.indirect.diffuse;
#endif

return emission;
}

inline void LightingBlinnPhong_GI (
SurfaceOutput s,
UnityGIInput data,
inout UnityGI gi)
{
gi = UnityGlobalIllumination (data, 1.0, s.Normal);
}

inline fixed4 LightingBlinnPhong_PrePass (SurfaceOutput s, half4 light)
{
fixed spec = light.a * s.Gloss;

fixed4 c;
c.rgb = (s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec);
c.a = s.Alpha;
return c;
}

#ifdef UNITY_CAN_COMPILE_TESSELLATION
struct UnityTessellationFactors {
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
#endif // UNITY_CAN_COMPILE_TESSELLATION

// Deprecated, kept around for existing user shaders.
#define UNITY_DIRBASIS \
const half3x3 unity_DirBasis = half3x3( \
half3( 0.81649658,  0.0,        0.57735027), \
half3(-0.40824830,  0.70710678, 0.57735027), \
half3(-0.40824830, -0.70710678, 0.57735027) \
);

// Deprecated, kept around for existing user shaders. Only sampling the flat lightmap now.
half3 DirLightmapDiffuse(in half3x3 dirBasis, fixed4 color, fixed4 scale, half3 normal, bool surfFuncWritesNormal, out half3 scalePerBasisVector)
{
return DecodeLightmap (color);
}

#endif


自定义灯光类型(包含上文的语法):

Custom Lighting models in Surface Shaders

When writing Surface Shaders, you’re describing properties of a surface (albedo color, normal, …) and the lighting interaction is computed by a
Lighting Model. Built-in lighting models are Lambert (diffuse lighting) and
BlinnPhong (specular lighting).

Sometimes you might want to use a custom lighting model, and it is possible to do that in Surface Shaders. Lighting model is nothing more than a couple of Cg/HLSL functions that match some conventions. The built-in
Lambert
and
BlinnPhong
models are defined in
Lighting.cginc
file inside Unity ({unity install path}/Data/CGIncludes/Lighting.cginc on Windows,
/Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc on Mac).

Lighting Model declaration

Lighting model is a couple of regular functions with names starting with
Lighting
. They can be declared anywhere in your shader file or one of included files. The functions are:

half4 Lighting<Name> (SurfaceOutput s, UnityGI gi);
This is used in forward rendering path for light models that
are not view direction dependent (e.g. diffuse).

half4 Lighting<Name> (SurfaceOutput s, half3 viewDir, UnityGI gi);
This is used in forward rendering path for light models that are view direction dependent.

half4 Lighting<Name>_Deferred (SurfaceOutput s, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal);
This is used in deferred lighting path.

half4 Lighting<Name>_PrePass (SurfaceOutput s, half4 light);
This is used in light prepass (legacy deferred) lighting path.

Note that you don’t need to declare all functions. A lighting model either uses view direction or it does not. Similarly, if the lighting model only works in forward, do not declare the
_Deferred
or
_Prepass
function. This way, all Shaders that use it compile to forward rendering only.

Custom GI

Similarly, customize the decoding lightmap data and probes by declaring the function below.

half4 Lighting<Name>_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi);

Note that to decode standard Unity lightmaps and SH probes, you can use the built-in
DecodeLightmap and ShadeSHPerPixel functions, as seen in
UnityGI_Base in the
UnityGlobalIllumination.cginc
file inside Unity ({unity install path}/Data/CGIncludes/UnityGlobalIllumination.cginc on Windows,
/Applications/Unity/Unity.app/Contents/CGIncludes/UnityGlobalIllumination.cginc on Mac).

Examples

Surface Shader Lighting Examples
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐