UnityShader基础光照效果

0x00 Surface Shader 常用的三种输出数据格式


//标准输出,若自定义输出必须带上以下所列参数
struct SurfaceOutput{
    fixed3 Albedo;  // diffuse color
    fixed3 Normal;  // tangent space normal, if written
    fixed3 Emission;
    half Specular;  // specular power in 0..1 range
    fixed Gloss;    // specular intensity
    fixed Alpha;    // alpha for transparencies
};

//基于物理光照模型标准输出
struct SurfaceOutputStandard{
    fixed3 Albedo;      // base (diffuse or specular) color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Metallic;      // 0=non-metal, 1=metal
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};
struct SurfaceOutputStandardSpecular{
    fixed3 Albedo;      // diffuse color
    fixed3 Specular;    // specular color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

 

0x01 Surface Shader compile directives


Surface shader编码在CGPROGRAM...ENDCG块内

  • 必须在Subshader块内而不能在pass内部,Surface shader将自己编译成多个通道.
  • 必须使用#pragma surface surfaceFunction lightModel [optionalparams] 指令来表明这是surface shader.

#pragma surface surfaceFunction lightModel [optionalparams]

蓝色必要要参数:require params

surfaceFunction

格式void surf (Input IN, inout SurfaceOutput o)Input自定义结构常必须包含纹理坐标和其他自需变量

lightModel

Standard lighting

使用SurfaceOutputStandard

StandardSpecular lighting

使用SurfaceOutputStandardSpecular

Lambert and BlinnPhong

不支持基于物理照明,低端设备用


surfaceFunction Input参数

//surfaceFunction 中Input参数纹理坐标必须带uvuv2
struct Input
{
    //纹理坐标用uv_或uv2_前缀指示,必须!
    float2 uv_myMainTex;//uv_XXX;
    //---以下为可选---
    float3 viewDir;    //视图方向为了计算时差、边缘光照等效果,Input需要包含视图方向
    float4 color;      //每个顶点颜色值
    float4 screenPos;  //屏幕空间位置,为了获得反射效果
    float3 worldPos;   //世界坐标空间
    float3 worldRefl;  //世界空间反射向量,surface shader不能写入o.Normal参数
    float3 worldNormal;//世界空间法向量,surface shader不能写入o.Normal参数

    //世界坐标反射向量,surface shader必须写入o.Normal参数
    //基于逐像素法线贴图获得反射向量,请使用WorldReflectionVector(IN,o.Normal)
    float3 worldRefl;INTERNAL_DATA;
    //世界坐标法线向量,surface shader必须写入o.Normal参数
    //基于逐像素法线贴图获得反射向量,请使用WorldReflectionVector(IN,o.Normal)
    float3 worldNormal;INTERNAL_DATA;
}

橙色可选参数:optional params

Transparency and alpha testing

使用alpha and alphatest指令

alpha

alpha:auto


fade-transparencypremultiplied transparency

alpha:blend

混合

alpha:fade

淡出

alpha:premul

预乘(使半透明表面保留适当的镜面反射)

alphatest:VariableName

基于给定变量值执行cutout

keepalpha

始终在alpha channel写入1.0

decal:add

叠加在表面上,并执行叠加混合

decal:blend

Alpha混合


Custom modifier functions用于计算更改输入的顶点数据,或更改最终计算的片元色

vertex:VertexFunction

修改计算per-vertex data

finalcolor:ColorFunction

 

finalgbuffer:ColorFunction

deferred path生效

finalprepass:ColorFunction

forward path生效。base path


Shadows and Tessellation 阴影和网格细分

addshadow

 

fullforwardshadows

forward path下,除了支持默认的一个方向光阴影,还可支持点光和聚光阴影

tessellate:TessFunction

//待详细补充


Code generation options

调整生成着色器代码选项,使得shader更小加载更快

exclude_path:deferred,

exclude_path:forward,

exclude_path:prepass


不给指定的渲染路径生成passes

noshadow

关闭接受所有阴影

noambient

不使用环境光和探头

novertexlights

forward path下禁用探头和逐顶点光照

nolightmap

关闭所有光照贴图

nodynlightmap

禁用运行时动态GI

nodirlightmap

不支持方向光光照贴图

nofog

禁用所有内置fog

nometa

不生成meta pass(提取光照贴图和GI信息用)

noforwardadd

禁用forward pathadditive pass,支持一个完整的方向光和所有逐顶点/SH计算的光

nolppv

不再支持Light Probe Proxy Volume组件

noshadowmask

禁用阴影遮罩


Miscellaneous options 各种其他选项

softvegetation

only be rendered Soft Vegetation

interpolateview

在顶点着色器中计算视图方向并进行插值;而不是在像素着色器中计算它。这可以使像素着色更快,但会消耗更多的纹理插值器。

halfasview

传递半角向量而不是视图向量到光照函数。半角向量将被逐顶点计算和标准化。这更快,但不完全正确。

approxview

被遗弃了。interpolateview

dualforward

基本不用(官方内置shader没搜到)

dithercrossfade

使表面着色器支持抖动效果。然后,您可以将这个着色器应用到GameObjects中,这些GameObjects使用为交叉淡入过渡模式配置的LOD组组件。


 

表面着色器的工作原理

clip_image002[8]

0x02 Surface Shader Light Model


直接照明和间接照明,间接照明可以理解为光照烘焙。下面是Unity自带的直接照明模型:

Lighting.cginc

UnityLambertLight

基于非物理的漫反射

LightingLambert

//..

LightingLambert_Deferred

//..

LightingLambert_PrePass

//..

UnityBlinnPhongLight

基于非物理的镜面高光

LightingBlinnPhong

//..

LightingBlinnPhong_Deferred

//..

LightingBlinnPhong_PrePass

//..

LightingLambert_GI

//..

LightingBlinnPhong_GI

//..

 

自定义光照函数表及说明:

格式:Lighting+ [自定义部分] + [_path]//要去掉中括号, _path是可选的,例如

LightingMyPhongforward path路径;LightingMyPhong_Deffereddeffered自动识别后缀,不加默认是forward path.

//orward path,不依赖视线方向向量:
half4 Lighting<Name> (SurfaceOutput s, UnityGI gi)

//在forward path,依赖视线方向向量
//half4 Lighting<Name> (SurfaceOutput s, half3 viewDir, UnityGI gi)
 
//在deferred lighting paths
half4 Lighting<Name>_Deferred (
      SurfaceOutput s,                  //标准输出结构
      UnityGI gi,                       //全局光照
      out half4 outDiffuseOcclusion,    //漫反射rgb+剔除alpha组合
      out half4 outSpecSmoothness,      //高光rgb+平滑alpha组合
      out half4 outNormal               //法线
)//后面三个参数在UnityStandardDataToGbuffer计算编码传递给GBuffer

//在Use this in light prepass (legacy deferred) lighting paths. 
//in light prepass (legacy deferred) lighting paths
half4 Lighting<Name>_PrePass (SurfaceOutput s, half4 light)

//自定义GI解析光照贴图和探针数据
half4 Lighting<Name>_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi)


自带常用Lambert and BlinnPhong lighting models

漫反射和Lambert模型

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;
}

镜面高光BlinnPhong模型

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;
 }

0x03 Example


自带的两个光照模型对比:

image

把SurfaceShader中光照函数翻译为VFShader

Lambert -逐像素

struct v2f {
    float4 pos        :SV_POSITION;
    float2 uv        :TEXCOORD0;
    float3 lightDir    :TEXCOORD1;
    float3 normal    :TEXCOORD2;
};
v2f m_vert(appdata_full v) {
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    //Transforms 2D UV by scale/bias property
    //#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    // Computes object space light direction
    o.lightDir = ObjSpaceLightDir(v.vertex);
    o.normal = v.normal;
    return o;
}
fixed4 m_frag(v2f i) : COLOR{
     float4 c = tex2D(_MainTex,i.uv);
     i.lightDir = normalize(i.lightDir);
     i.normal = normalize(i.normal);
     float diff = max(0,dot(i.normal,i.lightDir));

     return c * _LightColor0 * diff;
}

BlinnPhong -逐像素

struct v2f {
     float4 pos        :SV_POSITION;
     float2 uv          :TEXCOORD0;
     float3 lightDir   :TEXCOORD1;
     float3 viewDir  :TEXCOORD2;
     float3 normal    :TEXCOORD3;
};
v2f m_vert(appdata_full v) {
     v2f o;
     o.pos = UnityObjectToClipPos(v.vertex);
     //Transforms 2D UV by scale/bias property
     //#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
     // Computes object space light direction
     o.lightDir    = ObjSpaceLightDir(v.vertex);
     o.viewDir    = ObjSpaceViewDir(v.vertex);
     o.normal    = v.normal;
     return o;
} 

fixed4 m_frag(v2f i) : COLOR{
     float4 c = tex2D(_MainTex,i.uv);
     i.lightDir = normalize(i.lightDir);
     i.viewDir = normalize(i.viewDir);
     i.normal = normalize(i.normal);
     half3 h = normalize(i.lightDir + i.viewDir);
     float nh = max(0, dot(h, i.normal));
     float diff = max(0, dot(i.normal, i.lightDir));
     float spec = pow(nh, _Specular * 128) * _Gloss;
     c.rgb = c.rgb * _LightColor0.rgb * diff + _SpecColor.rgb * spec;
     return c;
}


 

原文地址:https://www.cnblogs.com/baolong-chen/p/11624840.html