• 关于Unity动态物体无法向使用使用custom shader和lightmap的物体投射阴影


      最近在做unity shader forge和marmoset的优化,TA那边遇到了一个阴影显示的问题,具体如下:

      在Forward Rendering状态下,静态场景使用了是shader forge生成的blendlayer类的shader,使用lightmap烘培贴图后,动态角色走到静态物体附近时,方向光在角色上的投影,无法投射到使用shader forge材质的物体上,但其他材质和使用marmoset的材质可以正常接收。查询了一些网站解决方案后,最终确定是custom shader 写法的问题,shader forge生成的shader属于自己实现vs和ps的功能,和写surface shader不同,除了着色用的shader pass("LightMode" = "ForwardBase")外需要Cast shadow用的第2个pass {"LightMode" = "ForwardAdd"}。
     
    下面是一个参考方案的代码
    1.   1 "Test" {
        2     SubShader {
        3         Tags { "RenderType" = "Opaque"}
        4 
        5         // This pass acts the same as the surface shader first pass.
        6         // Calculates per-pixel the most important directional light with shadows,
        7         // then per-vertex the next 4 most important lights,
        8         // then per-vertex spherical harmionics the rest of the lights,
        9         // and the ambient light value.
       10  
       11         Pass {
       12             Tags {"LightMode" = "ForwardBase"}
       13             CGPROGRAM
       14 
       15                 #pragma multi_compile_fwdbase
       16                 #pragma vertex vert
       17                 #pragma fragment frag
       18                 #pragma fragmentoption ARB_precision_hint_fastest
       19                 #include "UnityCG.cginc"
       20                 #include "AutoLight.cginc"
       21  
       22                 struct Input
       23                 {
       24                     float4 pos : SV_POSITION;
       25                     float3 vlight : COLOR;
       26                     float3 lightDir : TEXCOORD1;
       27                     float3 vNormal : TEXCOORD2;
       28                     LIGHTING_COORDS(3,4)
       29                 };
       30  
       31                 Input vert(appdata_full v)
       32                 {
       33                     Input o;
       34                     o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
       35                     // Calc normal and light dir.
       36                     o.lightDir = normalize(ObjSpaceLightDir(v.vertex));
       37                     o.vNormal = normalize(v.normal).xyz;
       38  
       39                     // Calc spherical harmonics and vertex lights. Ripped from compiled surface shader
       40                     float3 worldPos = mul(_Object2World, v.vertex).xyz;
       41                     float3 worldNormal = mul((float3x3)_Object2World, SCALED_NORMAL);
       42                     o.vlight = float3(0);
       43                     #ifdef LIGHTMAP_OFF
       44  
       45                         float3 shlight = ShadeSH9(float4(worldNormal, 1.0));
       46                         o.vlight = shlight;
       47                         #ifdef VERTEXLIGHT_ON
       48                             o.vlight += Shade4PointLights (
       49  
       50                                 unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
       51  
       52                                 unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
       53  
       54                                 unity_4LightAtten0, worldPos, worldNormal
       55  
       56                                 );
       57  
       58                         #endif // VERTEXLIGHT_ON
       59                     #endif // LIGHTMAP_OFF
       60                     TRANSFER_VERTEX_TO_FRAGMENT(o);
       61                     return o;
       62                 }
       63  
       64                 float4 _LightColor0; // Contains the light color for this pass.
       65 
       66                 half4 frag(Input IN) : COLOR
       67                 {
       68                     IN.lightDir = normalize ( IN.lightDir );
       69                     IN.vNormal = normalize ( IN.vNormal );
       70  
       71                     float atten = LIGHT_ATTENUATION(IN);
       72                     float3 color;
       73                     float NdotL = saturate( dot (IN.vNormal, IN.lightDir ));
       74                     color = UNITY_LIGHTMODEL_AMBIENT.rgb * 2;
       75  
       76                     color += IN.vlight;
       77  
       78                     color += _LightColor0.rgb * NdotL * ( atten * 2);
       79                     return half4(color, 1.0f);
       80                  }
       81  
       82             ENDCG
       83         }
       84  
       85         // Take this pass out if you don't want extra per-pixel lights.
       86         // Just set the other lights' Render Mode to "Not Important",
       87         // and they will be calculated as Spherical Harmonics or Vertex Lights in the above pass instead.
       88  
       89         Pass {
       90  
       91             Tags {"LightMode" = "ForwardAdd"}
       92  
       93             CGPROGRAM
       94 
       95                 #pragma multi_compile_fwdadd
       96                 #pragma vertex vert
       97                 #pragma fragment frag
       98                 #pragma fragmentoption ARB_precision_hint_fastest
       99                 #include "UnityCG.cginc"
      100                  #include "AutoLight.cginc"
      101 
      102                 struct Input
      103                 {
      104                     float4 pos : SV_POSITION;
      105                     float3 lightDir : TEXCOORD1;
      106                     float3 vNormal : TEXCOORD2;
      107                 }; 
      108  
      109                 Input vert(appdata_full v)
      110                  { 
      111                     Input o;
      112                     o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
      113  
      114                     // Calc normal and light dir.
      115                     o.lightDir = normalize(ObjSpaceLightDir(v.vertex));
      116                     o.vNormal = normalize(v.normal).xyz;
      117  
      118                     // Don't need any ambient or vertex lights in here as this is just an additive pass for each extra light.
      119                     // Shadows won't work here, either.
      120                     return o;
      121                 }
      122   
      123                 float4 _LightColor0; // Contains the light color for this pass.
      124 
      125                 half4 frag(Input IN) : COLOR
      126                 {
      127                     IN.lightDir = normalize ( IN.lightDir );
      128                     IN.vNormal = normalize ( IN.vNormal );
      129                  
      130                     float3 color;
      131                     float NdotL = saturate( dot (IN.vNormal, IN.lightDir ));
      132                     color = _LightColor0.rgb * NdotL;
      133                     return half4(color, 1.0f); 
      134                 }
      135 
      136             ENDCG
      137  
      138         }
      139     }
      140  
      141     FallBack "Diffuse"
      142  
      143 }
     
    而使用surface shader时候,只需要在声明surface时,设置制定的option(fullforwardshadows)就可以了
    1. #pragma surface MarmosetSurfMarmosetDirect vertex:MarmosetVert fullforwardshadows
    回过头来说shader forge插件,场景左侧使用sf生成的shader,use lightmap后,实时阴影果断看不到了
     
    左边木板为surface shader,右边为VS+PS Shader,阴影无法投射到石头上
     
    将shader forge设置为multi-light,他会自动生成ForwardAdd的pass,这样阴影就显示出来了。但照明效果也完全变了样子
     
    这个问题,在shader forge的论坛上也有提过,作者也说修改过这个bug了,但实际上最新的0.36还是没有完全解决
     
    如果设置ForwardAdd后还没有投影,可以把light的lightmapping 设置为realtimeOnly。或者是再复制一个投影的主光源。

     
    结论,Shader forge还是慎用吧,而且shader node也远没有比sky shop这类 uber shader要节省,为了投影,导致使用lightmap和real time的效果差别很大,
    完全是得不偿失的。
     
     
     
     
     
     
     
     
     





  • 相关阅读:
    vue-awesome-swiper 子项目内容高度适配问题
    ajax的原理及应用
    display:none opacity:0以及visibility:hidden的区别
    javascript 创建型设计模式
    圣杯布局和双飞翼布局
    javascript->对象继承
    js 宏任务和微任务
    android->按钮底部定位上移
    ios移动端开发的坑
    jvm系列 (五) ---类加载机制
  • 原文地址:https://www.cnblogs.com/TracePlus/p/4023913.html
走看看 - 开发者的网上家园