zoukankan      html  css  js  c++  java
  • 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;
    }


     

  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/baolong-chen/p/11624840.html
Copyright © 2011-2022 走看看