• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Unity Shader入门学习2前向渲染和延迟渲染

武飞扬头像
夜见黎明
帮助1

1.前向渲染

(1)

  1.  
    Shader "Unlit/001"
  2.  
    {
  3.  
    Properties
  4.  
    {
  5.  
    _MainTex("Main Tex", 2D) = "white"{} // 纹理贴图
  6.  
    _Diffuse("Diffuse",Color) = (1,1,1,1)
  7.  
    _Specular("Specular", Color) = (1,1,1,1)
  8.  
    _Gloss("Gloss", Range(8.0, 256)) = 20
  9.  
    }
  10.  
     
  11.  
     
  12.  
    //前向渲染路径原理:渲染对象的渲染图元,并计算两个缓冲区(深度与颜色缓冲区)。深度决定片元是否可见。可见则更新颜色缓冲区颜色值
  13.  
    //对每个逐像素光照,都要进行一次上述的过程。若物体被多个逐像素光照影响,则物体执行多个pass,每个物体执行一次逐像素光照计算。
  14.  
    //N个物体M个逐像素光照,N*M个pass
  15.  
     
  16.  
    //Base pass不仅可以处理逐像素光照,还可以处理其他。如逐顶点光照,球鞋函数。
  17.  
    //前向渲染有两种pass。一个是BasePass,一个AdditionPass
  18.  
    //BasePass计算最主要的平行光(最亮的,没有则不处理。只有这个光逐像素处理),环境光,自发光。逐顶点/SH光源和Lightmaps.默认支持阴影。 只会执行一次。
  19.  
    //AdditionPass计算额外的逐像素光源,每个pass对应一个光源。这里的光源类型不定,但一定是逐像素。
  20.  
    SubShader
  21.  
    {
  22.  
    Tags { "RenderType" = "Opaque" }
  23.  
    LOD 100
  24.  
     
  25.  
    Pass {//前向渲染中Base Pass
  26.  
    Tags{"LightMode" = "ForwardBase"}
  27.  
    CGPROGRAM
  28.  
    #pragma multi_compile_fwdbase
  29.  
    //这个指令可以保证我们在shder中使用光照衰减等光照变量可以被正确赋值
  30.  
     
  31.  
    #pragma vertex vert
  32.  
    #pragma fragment frag
  33.  
    #include "UnityCG.cginc"
  34.  
    #include "Lighting.cginc"
  35.  
     
  36.  
    fixed4 _Diffuse;
  37.  
    fixed4 _Specular;
  38.  
    float _Gloss;
  39.  
    sampler2D _MainTex;
  40.  
    float4 _MainTex_ST;
  41.  
     
  42.  
    struct a2v
  43.  
    {
  44.  
    float4 vertex : POSITION;
  45.  
    float3 normal:NORMAL;
  46.  
    float4 texcoord:TEXCOORD0;
  47.  
     
  48.  
    };
  49.  
     
  50.  
    struct v2f
  51.  
    {
  52.  
    float4 vertex : SV_POSITION;
  53.  
    float3 worldNormal : TEXCOORD0;
  54.  
    float3 worldPos:TEXCOORD1;
  55.  
    float2 uv : TEXCOORD2;
  56.  
     
  57.  
    float3 vertexLight : TEXCOORD3;//顶点光照与球鞋光照
  58.  
    };
  59.  
     
  60.  
    v2f vert (a2v v)
  61.  
    {
  62.  
    v2f f;
  63.  
    f.vertex = UnityObjectToClipPos(v.vertex);
  64.  
    f.worldNormal = UnityObjectToWorldNormal(v.normal);
  65.  
    f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  66.  
     
  67.  
    f.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
  68.  
     
  69.  
    //下面是顶点光源与球鞋光源的计算
  70.  
    #ifdef LIGHTMAP_OFF
  71.  
    // LIGHTMAP关闭才会计算球鞋,顶点光照
  72.  
    float3 shLight = ShadeSH9(float4(v.normal,0.3));//球鞋光源。传入法线。
  73.  
    f.vertexLight = shLight;
  74.  
     
  75.  
    #ifdef VERTEXLIGHT_ON
  76.  
    //顶点光源开启时
  77.  
    float3 vertexLight = Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,
  78.  
    unity_LightColor[0].rgb,unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb,
  79.  
    unity_4LightAtten0, f.worldPos, f.worldNormal);
  80.  
    f.vertexLight = vertexLight;
  81.  
    #endif
  82.  
    #endif
  83.  
    return f;
  84.  
    }
  85.  
     
  86.  
    fixed4 frag (v2f i) : SV_Target
  87.  
    {
  88.  
    //然后在Base Pass中处理场景中的最重要的平行光
  89.  
    //如果场景中包含了多个平行光,
  90.  
    //Unity会选择最亮的平行光传递给Base Pass进行逐像素处理,
  91.  
    //其他平行光会按照逐顶点或在Additional Pass中按逐像素的方式处理。
  92.  
    //_LightColor0得到平行光强度
  93.  
     
  94.  
    fixed3 worldNormal = normalize(i.worldNormal);
  95.  
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  96.  
     
  97.  
    fixed3 albedo =tex2D(_MainTex,i.uv).rgb* _Diffuse.rgb;
  98.  
    fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT*albedo;
  99.  
     
  100.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal,worldLightDir))*albedo;
  101.  
     
  102.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  103.  
    //fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.WorldPos));
  104.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  105.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(worldNormal,halfDir)),_Gloss);
  106.  
     
  107.  
    return fixed4(ambient diffuse specular i.vertexLight, 1);
  108.  
    }
  109.  
    ENDCG
  110.  
    }
  111.  
     
  112.  
     
  113.  
    Pass//前向渲染中Additional Pass
  114.  
    {
  115.  
    Tags{"LightMode" = "ForwardAdd"}
  116.  
     
  117.  
    Blend One One
  118.  
    //开启并设置混合模式。光照是混合而非覆盖。(还可以换成其他混合模式)
  119.  
     
  120.  
    CGPROGRAM
  121.  
    #pragma multi_compile_fwdadd
  122.  
    #pragma vertex vert
  123.  
    #pragma fragment frag
  124.  
     
  125.  
    #include "Lighting.cginc"
  126.  
    #include "AutoLight.cginc"
  127.  
     
  128.  
    fixed4 _Diffuse;
  129.  
    fixed4 _Specular;
  130.  
    float _Gloss;
  131.  
     
  132.  
    struct a2v
  133.  
    {
  134.  
    float4 vertex:POSITION;
  135.  
    float3 normal :NORMAL;
  136.  
    };
  137.  
     
  138.  
    struct v2f
  139.  
    {
  140.  
    float4 pos :SV_POSITION;
  141.  
    float3 worldNormal : TEXCOORD0;
  142.  
    float3 worldPos : TEXCOORD1;
  143.  
     
  144.  
    LIGHTING_COORDS(2,3)//与光照衰减相关。2,3分别指TEXCOORD2,3
  145.  
    };
  146.  
     
  147.  
    v2f vert(a2v v)
  148.  
    {
  149.  
    v2f f;
  150.  
    f.pos = UnityObjectToClipPos(v.vertex);
  151.  
    f.worldNormal = UnityObjectToWorldNormal(v.normal);
  152.  
    f.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
  153.  
     
  154.  
    TRANSFER_VERTEX_TO_FRAGMENT(f);
  155.  
    return f;
  156.  
    }
  157.  
     
  158.  
    fixed4 frag(v2f f):SV_Target
  159.  
    {
  160.  
    fixed3 worldNormal = normalize(f.worldNormal);
  161.  
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(f.worldPos));
  162.  
     
  163.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0,dot(worldNormal,worldLightDir));
  164.  
     
  165.  
    fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldPos));
  166.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  167.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(viewDir,halfDir)),_Gloss);
  168.  
     
  169.  
    fixed atten = LIGHT_ATTENUATION(f);//计算衰减。已经为不同类型光源做出适应
  170.  
     
  171.  
    return fixed4((diffuse specular)*atten,1.0);
  172.  
    }
  173.  
     
  174.  
    ENDCG
  175.  
    }
  176.  
    }
  177.  
    }
学新通

(2)

  1.  
    //最基础功能:Base中接收平行光环境光,add里接收其他逐像素光源并计算衰减(base里没有添加顶点光源与球鞋光源处理)
  2.  
     
  3.  
    Shader "09-1" {
  4.  
    Properties {
  5.  
    _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
  6.  
    _Specular ("Specular", Color) = (1, 1, 1, 1)
  7.  
    _Gloss ("Gloss", Range(8.0, 256)) = 20
  8.  
    }
  9.  
    SubShader {
  10.  
    Tags { "RenderType"="Opaque" }
  11.  
     
  12.  
    //Base Pass
  13.  
    Pass {
  14.  
    // Pass for ambient light & first pixel light (directional light)
  15.  
    Tags { "LightMode"="ForwardBase" }
  16.  
     
  17.  
    CGPROGRAM
  18.  
     
  19.  
     
  20.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  21.  
    #pragma multi_compile_fwdbase
  22.  
     
  23.  
    #pragma vertex vert
  24.  
    #pragma fragment frag
  25.  
     
  26.  
    #include "Lighting.cginc"
  27.  
     
  28.  
    fixed4 _Diffuse;
  29.  
    fixed4 _Specular;
  30.  
    float _Gloss;
  31.  
     
  32.  
    struct a2v {
  33.  
    float4 vertex : POSITION;
  34.  
    float3 normal : NORMAL;
  35.  
    };
  36.  
     
  37.  
    struct v2f {
  38.  
    float4 pos : SV_POSITION;
  39.  
    float3 worldNormal : TEXCOORD0;
  40.  
    float3 worldPos : TEXCOORD1;
  41.  
    };
  42.  
     
  43.  
    v2f vert(a2v v) {
  44.  
    v2f f;
  45.  
    f.pos = UnityObjectToClipPos(v.vertex);
  46.  
     
  47.  
    f.worldNormal = UnityObjectToWorldNormal(v.normal);
  48.  
     
  49.  
    f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  50.  
     
  51.  
    return f;
  52.  
    }
  53.  
     
  54.  
    fixed4 frag(v2f i) : SV_Target {
  55.  
    fixed3 worldNormal = normalize(i.worldNormal);
  56.  
     
  57.  
    //_WorldSpaceLightPos0得到平行光方向
  58.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
  59.  
     
  60.  
    //Base Pass计算环境光
  61.  
    //只计算一次即可
  62.  
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
  63.  
     
  64.  
    //然后在Base Pass中处理场景中的最重要的平行光
  65.  
    //如果场景中包含了多个平行光,
  66.  
    //Unity会选择最亮的平行光传递给Base Pass进行逐像素处理,
  67.  
    //其他平行光会按照逐顶点或在Additional Pass中按逐像素的方式处理。
  68.  
    //_LightColor0得到平行光强度
  69.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
  70.  
     
  71.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  72.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  73.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
  74.  
     
  75.  
    //令平行光衰减值为1
  76.  
    fixed atten = 1.0;
  77.  
     
  78.  
    return fixed4(ambient (diffuse specular) * atten, 1.0);
  79.  
    }
  80.  
     
  81.  
    ENDCG
  82.  
    }
  83.  
     
  84.  
     
  85.  
    //Additional Pass
  86.  
    Pass {
  87.  
    // Pass for other pixel lights
  88.  
    Tags { "LightMode"="ForwardAdd" }
  89.  
     
  90.  
    //使用Blend命令开启和设置混合模式
  91.  
    //实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
  92.  
    Blend One One
  93.  
     
  94.  
    CGPROGRAM
  95.  
     
  96.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  97.  
    #pragma multi_compile_fwdadd
  98.  
     
  99.  
    #pragma vertex vert
  100.  
    #pragma fragment frag
  101.  
     
  102.  
    #include "Lighting.cginc"
  103.  
    #include "AutoLight.cginc"
  104.  
     
  105.  
    fixed4 _Diffuse;
  106.  
    fixed4 _Specular;
  107.  
    float _Gloss;
  108.  
     
  109.  
    struct a2v {
  110.  
    float4 vertex : POSITION;
  111.  
    float3 normal : NORMAL;
  112.  
    };
  113.  
     
  114.  
    struct v2f {
  115.  
    float4 pos : SV_POSITION;
  116.  
    float3 worldNormal : TEXCOORD0;
  117.  
    float3 worldPos : TEXCOORD1;
  118.  
    };
  119.  
     
  120.  
    v2f vert(a2v v) {
  121.  
    v2f o;
  122.  
    o.pos = UnityObjectToClipPos(v.vertex);
  123.  
     
  124.  
    o.worldNormal = UnityObjectToWorldNormal(v.normal);
  125.  
     
  126.  
    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  127.  
     
  128.  
    return o;
  129.  
    }
  130.  
     
  131.  
    fixed4 frag(v2f i) : SV_Target {
  132.  
    fixed3 worldNormal = normalize(i.worldNormal);
  133.  
     
  134.  
    //判断当前处理的逐像素光源的类型
  135.  
    #ifdef USING_DIRECTIONAL_LIGHT
  136.  
    //如果是平行光,光源方向可以直接得到
  137.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
  138.  
    #else
  139.  
    //如果是点光源或聚光灯,
  140.  
    //光源方向需要用这个位置减去世界空间下的顶点位置。
  141.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
  142.  
    #endif
  143.  
     
  144.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
  145.  
     
  146.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  147.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  148.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
  149.  
     
  150.  
    //处理不同光源的衰减
  151.  
    #ifdef USING_DIRECTIONAL_LIGHT
  152.  
    fixed atten = 1.0;
  153.  
    #else
  154.  
    #if defined (POINT)
  155.  
    //点光
  156.  
    float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
  157.  
    fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  158.  
    //使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
  159.  
    #elif defined (SPOT)
  160.  
    //聚光
  161.  
    float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
  162.  
    fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w 0.5).w
  163.  
    * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  164.  
    #else
  165.  
    fixed atten = 1.0;
  166.  
    #endif
  167.  
    #endif
  168.  
     
  169.  
    return fixed4((diffuse specular) * atten, 1.0);
  170.  
    }
  171.  
     
  172.  
    ENDCG
  173.  
    }
  174.  
    }
  175.  
    FallBack "Specular"
  176.  
    }
  177.  
     
学新通

(3)

  1.  
    //接收来自平行光的阴影
  2.  
     
  3.  
    Shader "09-2" {
  4.  
    Properties {
  5.  
    _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
  6.  
    _Specular ("Specular", Color) = (1, 1, 1, 1)
  7.  
    _Gloss ("Gloss", Range(8.0, 256)) = 20
  8.  
    }
  9.  
    SubShader {
  10.  
    Tags { "RenderType"="Opaque" }
  11.  
     
  12.  
    //Base Pass
  13.  
    Pass {
  14.  
    // Pass for ambient light & first pixel light (directional light)
  15.  
    Tags { "LightMode"="ForwardBase" }
  16.  
     
  17.  
    CGPROGRAM
  18.  
     
  19.  
    #pragma multi_compile_fwdbase
  20.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  21.  
     
  22.  
    #pragma vertex vert
  23.  
    #pragma fragment frag
  24.  
    #include "Lighting.cginc"
  25.  
     
  26.  
    #include "AutoLight.cginc"
  27.  
    //该文件声明计算阴影时用的宏
  28.  
     
  29.  
    fixed4 _Diffuse;
  30.  
    fixed4 _Specular;
  31.  
    float _Gloss;
  32.  
     
  33.  
    struct a2v {
  34.  
    float4 vertex : POSITION;
  35.  
    float3 normal : NORMAL;
  36.  
    };
  37.  
     
  38.  
    struct v2f {
  39.  
    float4 pos : SV_POSITION;
  40.  
    float3 worldNormal : TEXCOORD0;
  41.  
    float3 worldPos : TEXCOORD1;
  42.  
     
  43.  
    SHADOW_COORDS(2)
  44.  
    //添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
  45.  
    //由于已经占用了2个插值寄存器,
  46.  
    //因此传入的参数是2,阴影纹理坐标将占用第三个寄存器。
  47.  
    };
  48.  
     
  49.  
    v2f vert(a2v v) {
  50.  
    v2f f;
  51.  
    f.pos = UnityObjectToClipPos(v.vertex);
  52.  
     
  53.  
    f.worldNormal = UnityObjectToWorldNormal(v.normal);
  54.  
     
  55.  
    f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  56.  
     
  57.  
    TRANSFER_SHADOW(f);//计算v2f中声明的阴影纹理坐标
  58.  
     
  59.  
    return f;
  60.  
    }
  61.  
     
  62.  
    fixed4 frag(v2f i) : SV_Target {
  63.  
    fixed3 worldNormal = normalize(i.worldNormal);
  64.  
     
  65.  
    //_WorldSpaceLightPos0得到平行光方向
  66.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
  67.  
     
  68.  
    //Base Pass计算环境光
  69.  
    //只计算一次即可
  70.  
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
  71.  
     
  72.  
    fixed shadow = SHADOW_ATTENUATION(i);//使用阴影坐标对阴影贴图进行采样
  73.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir))* shadow;
  74.  
     
  75.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  76.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  77.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss)* shadow;//最后乘上阴影值shadow
  78.  
     
  79.  
    //令平行光衰减值为1
  80.  
    fixed atten = 1.0;
  81.  
     
  82.  
    return fixed4(ambient (diffuse specular) * atten, 1.0);
  83.  
    }
  84.  
     
  85.  
    ENDCG
  86.  
    }
  87.  
     
  88.  
     
  89.  
    //Additional Pass
  90.  
    Pass {
  91.  
    // Pass for other pixel lights
  92.  
    Tags { "LightMode"="ForwardAdd" }
  93.  
     
  94.  
    //使用Blend命令开启和设置混合模式
  95.  
    //实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
  96.  
    Blend One One
  97.  
     
  98.  
    CGPROGRAM
  99.  
     
  100.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  101.  
    #pragma multi_compile_fwdadd
  102.  
     
  103.  
    #pragma vertex vert
  104.  
    #pragma fragment frag
  105.  
     
  106.  
    #include "Lighting.cginc"
  107.  
    #include "AutoLight.cginc"
  108.  
     
  109.  
    fixed4 _Diffuse;
  110.  
    fixed4 _Specular;
  111.  
    float _Gloss;
  112.  
     
  113.  
    struct a2v {
  114.  
    float4 vertex : POSITION;
  115.  
    float3 normal : NORMAL;
  116.  
    };
  117.  
     
  118.  
    struct v2f {
  119.  
    float4 pos : SV_POSITION;
  120.  
    float3 worldNormal : TEXCOORD0;
  121.  
    float3 worldPos : TEXCOORD1;
  122.  
    };
  123.  
     
  124.  
    v2f vert(a2v v) {
  125.  
    v2f o;
  126.  
    o.pos = UnityObjectToClipPos(v.vertex);
  127.  
     
  128.  
    o.worldNormal = UnityObjectToWorldNormal(v.normal);
  129.  
     
  130.  
    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  131.  
     
  132.  
    return o;
  133.  
    }
  134.  
     
  135.  
    fixed4 frag(v2f i) : SV_Target {
  136.  
    fixed3 worldNormal = normalize(i.worldNormal);
  137.  
     
  138.  
    //判断当前处理的逐像素光源的类型
  139.  
    #ifdef USING_DIRECTIONAL_LIGHT
  140.  
    //如果是平行光,光源方向可以直接得到
  141.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
  142.  
    #else
  143.  
    //如果是点光源或聚光灯,
  144.  
    //光源方向需要用这个位置减去世界空间下的顶点位置。
  145.  
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
  146.  
    #endif
  147.  
     
  148.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
  149.  
     
  150.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  151.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  152.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
  153.  
     
  154.  
    //处理不同光源的衰减
  155.  
    #ifdef USING_DIRECTIONAL_LIGHT
  156.  
    fixed atten = 1.0;
  157.  
    #else
  158.  
    #if defined (POINT)
  159.  
    //点光
  160.  
    float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
  161.  
    fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  162.  
    //使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
  163.  
    #elif defined (SPOT)
  164.  
    //聚光
  165.  
    float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
  166.  
    fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w 0.5).w
  167.  
    * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  168.  
    #else
  169.  
    fixed atten = 1.0;
  170.  
    #endif
  171.  
    #endif
  172.  
     
  173.  
    return fixed4((diffuse specular) * atten, 1.0);
  174.  
    }
  175.  
     
  176.  
    ENDCG
  177.  
    }
  178.  
    }
  179.  
    FallBack "Specular"
  180.  
    }
  181.  
     
学新通
  1.  
    //统一管理衰减与阴影
  2.  
     
  3.  
    Shader "09-3" {
  4.  
    Properties {
  5.  
    _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
  6.  
    _Specular ("Specular", Color) = (1, 1, 1, 1)
  7.  
    _Gloss ("Gloss", Range(8.0, 256)) = 20
  8.  
    }
  9.  
    SubShader {
  10.  
    Tags { "RenderType"="Opaque" }
  11.  
     
  12.  
    //Base Pass
  13.  
    Pass {
  14.  
    // Pass for ambient light & first pixel light (directional light)
  15.  
    Tags { "LightMode"="ForwardBase" }
  16.  
     
  17.  
    CGPROGRAM
  18.  
     
  19.  
    #pragma multi_compile_fwdbase
  20.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  21.  
     
  22.  
    #pragma vertex vert
  23.  
    #pragma fragment frag
  24.  
    #include "Lighting.cginc"
  25.  
     
  26.  
    #include "AutoLight.cginc"
  27.  
    //该文件声明计算阴影时用的宏
  28.  
     
  29.  
    fixed4 _Diffuse;
  30.  
    fixed4 _Specular;
  31.  
    float _Gloss;
  32.  
     
  33.  
    struct a2v {
  34.  
    float4 vertex : POSITION;
  35.  
    float3 normal : NORMAL;
  36.  
    };
  37.  
     
  38.  
    struct v2f {
  39.  
    float4 pos : SV_POSITION;
  40.  
    float3 worldNormal : TEXCOORD0;
  41.  
    float3 worldPos : TEXCOORD1;
  42.  
     
  43.  
    SHADOW_COORDS(2)
  44.  
    //添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
  45.  
    //由于已经占用了2个插值寄存器,
  46.  
    //因此传入的参数是2,阴影纹理坐标将占用第三个寄存器。
  47.  
    };
  48.  
     
  49.  
    v2f vert(a2v v) {
  50.  
    v2f f;
  51.  
    f.pos = UnityObjectToClipPos(v.vertex);
  52.  
     
  53.  
    f.worldNormal = UnityObjectToWorldNormal(v.normal);
  54.  
     
  55.  
    f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  56.  
     
  57.  
    TRANSFER_SHADOW(f);//计算v2f中声明的阴影纹理坐标
  58.  
     
  59.  
    return f;
  60.  
    }
  61.  
     
  62.  
    fixed4 frag(v2f i) : SV_Target {
  63.  
    fixed3 worldNormal = normalize(i.worldNormal);
  64.  
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  65.  
     
  66.  
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
  67.  
     
  68.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
  69.  
     
  70.  
    fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
  71.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  72.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
  73.  
     
  74.  
    //用于计算光照衰减和阴影的宏,
  75.  
    //第一个参数用于存储将光照衰减和阴影值相乘后的结果。
  76.  
    //第二个参数是结构体v2f,这个参数会传递给SHADOW_ATTENUATION,用来计算阴影值。
  77.  
    //第三个参数是世界空间的坐标,用于计算光源空间下的坐标,再对光照衰减纹理釆样来得到光照衰减。
  78.  
    UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
  79.  
     
  80.  
    return fixed4(ambient (diffuse specular) * atten, 1.0);
  81.  
    }
  82.  
     
  83.  
    ENDCG
  84.  
    }
  85.  
     
  86.  
     
  87.  
    //Additional Pass
  88.  
    Pass {
  89.  
    // Pass for other pixel lights
  90.  
    Tags { "LightMode"="ForwardAdd" }
  91.  
     
  92.  
    //使用Blend命令开启和设置混合模式
  93.  
    //实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
  94.  
    Blend One One
  95.  
     
  96.  
    CGPROGRAM
  97.  
     
  98.  
    //保证在Shader中使用光照衰减等变量可以被正确赋值
  99.  
    #pragma multi_compile_fwdadd
  100.  
     
  101.  
    #pragma vertex vert
  102.  
    #pragma fragment frag
  103.  
     
  104.  
    #include "Lighting.cginc"
  105.  
    #include "AutoLight.cginc"
  106.  
    //该文件声明计算阴影时用的宏
  107.  
     
  108.  
    fixed4 _Diffuse;
  109.  
    fixed4 _Specular;
  110.  
    float _Gloss;
  111.  
     
  112.  
    struct a2v {
  113.  
    float4 vertex : POSITION;
  114.  
    float3 normal : NORMAL;
  115.  
    };
  116.  
     
  117.  
    struct v2f {
  118.  
    float4 pos : SV_POSITION;
  119.  
    float3 worldNormal : TEXCOORD0;
  120.  
    float3 worldPos : TEXCOORD1;
  121.  
    SHADOW_COORDS(2)
  122.  
    //添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
  123.  
    };
  124.  
     
  125.  
    v2f vert(a2v v) {
  126.  
    v2f o;
  127.  
    o.pos = UnityObjectToClipPos(v.vertex);
  128.  
     
  129.  
    o.worldNormal = UnityObjectToWorldNormal(v.normal);
  130.  
     
  131.  
    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  132.  
     
  133.  
    return o;
  134.  
    }
  135.  
     
  136.  
    fixed4 frag(v2f i) : SV_Target {
  137.  
    //fixed3 worldNormal = normalize(i.worldNormal);
  138.  
     
  139.  
    判断当前处理的逐像素光源的类型
  140.  
    //#ifdef USING_DIRECTIONAL_LIGHT
  141.  
    // //如果是平行光,光源方向可以直接得到
  142.  
    // fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
  143.  
    //#else
  144.  
    // //如果是点光源或聚光灯,
  145.  
    // //光源方向需要用这个位置减去世界空间下的顶点位置。
  146.  
    // fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
  147.  
    //#endif
  148.  
     
  149.  
    fixed3 worldNormal = normalize(i.worldNormal);
  150.  
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  151.  
     
  152.  
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
  153.  
     
  154.  
    fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
  155.  
    fixed3 halfDir = normalize(worldLightDir viewDir);
  156.  
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
  157.  
     
  158.  
    处理不同光源的衰减
  159.  
    //#ifdef USING_DIRECTIONAL_LIGHT
  160.  
    // fixed atten = 1.0;
  161.  
    //#else
  162.  
    // #if defined (POINT)
  163.  
    // //点光
  164.  
    // float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
  165.  
    // fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  166.  
    // //使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
  167.  
    // #elif defined (SPOT)
  168.  
    // //聚光
  169.  
    // float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
  170.  
    // fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w 0.5).w
  171.  
    // * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
  172.  
    // #else
  173.  
    // fixed atten = 1.0;
  174.  
    // #endif
  175.  
    //#endif
  176.  
     
  177.  
    UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
  178.  
     
  179.  
    return fixed4((diffuse specular)* atten, 1.0);
  180.  
     
  181.  
    }
  182.  
     
  183.  
    ENDCG
  184.  
    }
  185.  
    }
  186.  
    FallBack "Specular"
  187.  
    }
  188.  
     
学新通

2.延迟渲染

Shader "Unlit/002"
{
    Properties
    {
        _MainTex("Texture",2D) = "white" {}
        _Diffuse("Diffuse",Color) = (1,1,1,1)
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(8.0, 50)) = 20
    }


//延迟渲染主要包含了两个Pass。
//在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现
//当发现一个片元是可见的,我们就把它的相关信息存储到G缓冲区中。
//然后,在第二个Pass中,我们利用G缓冲区的各个片元信息进行真正的光照计算。

//不支持真正的抗锯齿(anti-aliasing)功能。
//不能处理半透明物体。
//对显卡有一定要求。如果要使用延迟渲染的话,显卡必须支持MRT (Multiple Render Targets)、Shader Mode 3.0及以上、深度渲染纹理以及双面的模板缓冲。

//伪代码
//Pass1
//{  
//    //第一个Pass不进行真正的光照计算  
//    //仅仅把光照计算需要的信息存储到G缓冲中  
//    for (each primitive in this model)
//    {  
//        for (each fragment covered by this primitive)
//        {  
//            if(failed in depth test)
//            {  
//                discard;  
//            }  
//            else
//            {  
//                //如果该片元可见  
//                //就把需要的信息存储到G缓冲中  
//                writeGBuffer(materialInfo,pos,normal,lightDir,viewDir);  
//            }  
//        }  
//    }  
//}

//Pass2
//{  
//    //利用G缓冲中的信息进行真正的光照计算  
//    for(each pixel in the screen)
//    {  
//        if(the pixel is valid)
//        {  
//            //如果该像素是有效的  
//            //读取它对应的G缓冲中的信息  
//            readGBuffer(pixel,materialInfo,pos,normal,lightDir,viewDir);  
//            //根据读到的信息进行光照计算  
//            float4 color = Shading(materialInfo,pos,normal,lightDir,viewDir);  
//            //更新帧缓冲  
//            writeFrameBuffer(pixel,color);  
//        }  
//    }  
//} 


    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100
        
        Pass

        {
            Tags{"LightMode" = "Deferred"}

            CGPROGRAM
            #pragma target 3.0
            #pragma vertex vert
            #pragma fragment frag
            #pragma exclude_renderers norm
            #pragma multi_compile __ UNITY_HDR_ON

            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Gloss;

            struct appdata
            {
                float4 vertex :POSITION;
                float2 uv : TEXCOORD0;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                float2 uv: TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
            };

            struct DeferredOutput
            {
                float4 gBuffer0 : SV_TARGET0;
                float4 gBuffer1 : SV_TARGET1;
                float4 gBuffer2 : SV_TARGET2;
                float4 gBuffer3 : SV_TARGET3;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv,_MainTex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                return o;
            }

            DeferredOutput frag(v2f i)
            {
                DeferredOutput o;
                fixed3 color = tex2D(_MainTex, i.uv).rgb * _Diffuse.rgb;
                o.gBuffer0.rgb = color;
                o.gBuffer0.a = 1;
                o.gBuffer1.rgb = _Specular.rgb;
                o.gBuffer1.a = _Gloss/50.0;
                o.gBuffer2 = float4(i.worldNormal * 0.5 0.5,1);
                #if !defined(UNITY_HDR_ON)
                    color.rgb = exp2(-color.rgb);
                #endif
                o.gBuffer3 = fixed4(color,1);
                return o;
            }

            ENDCG
        }
    }
}
 

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfgfbg
系列文章
更多 icon
同类精品
更多 icon
继续加载