UnityShader源码2017---学习笔记与自我拓展023

源自Mobile-Diffuse

本来不想继续看这个shader的,实在没有啥好说的,但是。但是。但是。。。

#pragma surface surf Lambert noforwardadd

把这里的noforwardadd之流的一起总结一下吧。

在官方文档里是这么写的

#pragma surface surfaceFunction lightModel [optionalparams]

我对号入座

surf----surfaceFunction

Lambert----lightModel

noforwardadd----[optionalparams]

关于surfaceFunction和lightModel的话,可以自定义的。这一块等后面有机会在展开说,其实也没有什么特殊的东西,按照unity的文档把命名弄好就可以了

扫描二维码关注公众号,回复: 1577192 查看本文章

简单的说一下吧

#pragma surface HHH SimpleLambert

half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten)

{

half NdotL = dot (s.Normal, lightDir);

half4 c;

c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten);

c.a = s.Alpha;

return c;

}

void HHH(*******){::::::::}

看一下对应关系就好了。

关于lightmodel多说一句(这里直说老版本的,PBR的部分以后再说吧)

unity自带的有Lambert BlinnPhong (PBR部分补充了两个Standard StandardSpecular


接下来进入正题[optionalparams](这部分都是官网的东西,我只为自己带盐,齁咸)

先来看一下blend commands

1.alpha   alpha:auto  alpha:fade alpha:blend

如果要这么写

#pragma surface surf Lambert alpha

这就相当于这是一个使用了Lambert光照模型的透明物体。

#pragma surface surf Lambert alpha:auto

以及

#pragma surface surf Lambert alpha:fade

以及

#pragma surface surf Lambert alpha:blend

根据测试结果,这4种alpha   alpha:auto  alpha:fade alpha:blend是相同的。额。。。。这么多相同的,难道我弄错了。。

看了一下complie出来的code,他们4个对于的blend都是Blend SrcAlpha OneMinusSrcAlpha.

2.alpha:premul

再来看一下

#pragma surface surf Lambert alpha:premul

这个premul一看就知道,pre前缀表示预先,前面什么的mul就是multiply的缩写,连在一起就是预乘

他对应的blend模式是Blend One OneMinusSrcAlpha.

这个模式很有意思。One * Current + OneMinusSrcAlpha * Pre

假如当前的图片的Alpha 是 1,那么得到的结果就是常见的结果(Blend SrcAlpha OneMinusSrcAlpha.),该咋地咋地

但是,如果当前的alpha为0,那么得到的结果就是相加变亮的结果了。

3.alpha:keepalpha

这个指令很有意思。mmp

#pragma surface surf Lambert alpha:keepalpha

写上之后先来这么个警告。。。说什么不认识keepalpha。。。但是unity的编辑器却很诚实的解析成功了。

Shader warning in 'ShaderStore/UnitShader2017/Mobile/Diffuse': Unrecognized #pragma surface directive: alpha:keepalpha at line 15

这个警告不知道该怎么说他。。。。忽略吧

然后继续测试,发现加了alpha:keepalpha之后跟没有加的情况都是一样的,看了compile的code之后,发现也是一样的。。

这就想起了那个警告。。。警告的作用出现了,“我不认识keepalpha,所以我就忽略了他”。。。

unity文档吃XXOO了吧,搞了这么一招,打的我体无完肤。

安装他字面的意思和官方的文档解释,应该出现的结果是https://blog.csdn.net/u012871784/article/details/80605036跟这个一样的结果。

就是说,在渲染rt的时候,alpha会保留原图alpha参与计算(对o.Alpha赋值的结果)之后的结果。而不是强制o.Alpha =1.0

对于这种情况。我采取的态度就是:呵呵

至此,alpha blend的方面的surfaceshader部分就结束了么。。。相加模式呢。。相乘模式呢。。。。

番外篇

blend one one
CGPROGRAM
#pragma surface surf Lambert

这些写貌似是正确的,但是参考compile之后,发现zwrite并没有关闭,也没有colormask rgb。

ZWrite Off
ColorMask RGB
Blend one one
CGPROGRAM
#pragma surface surf Lambert

然后就这么写了,看似完美。再次查看compile

发现在FRAGMENT shader部分

c_3.xyz = c_9.xyz;
c_3.w = 1.0 ;
gl_FragData[ 0 ] = c_3;

输出的alpha强制为1了。。。

于是再来了一次测试

ZWrite Off
ColorMask RGB
Blend srcalpha oneminussrcalpha
CGPROGRAM
#pragma surface surf Lambert

果然一点作用都没有。。。

于是就慌慌张张的得出一个结论:如果要使用blend的话,还是老实的自己去写vf去做吧

4.alphatest:VariableName

在properties里

_Cutoff ( "cutoff" ,range ( 0 , 1 )) = 0.5

在subsahder里

#pragma surface surf Lambert alphatest:_Cutoff

结果就是


后面那个片是用来接收阴影的(我有fallback的)

但是阴影不太对啊 ,阴影还是quad的影子。。。于是我看了一下官方的文档。。

官方的文档假装自己有AI一样。。。猜测我的需求

  • alphatest:VariableName - Enable alpha cutout transparency. Cutoff value is in a float variable with VariableName. You’ll likely also want to use addshadow directive to generate proper shadow caster pass.

然我我就加上了addshadow了

#pragma surface surf Lambert alphatest:_Cutoff addshadow

GOOD JOB!!!!

5.Decal:add

#pragma surface surf Lambert decal:add

如果图片设置了Fadeout Mip Maps的话。

就会出现这样的效果。


只是不明白为啥不是透明掉,而是变成了白色

于是。。

#pragma surface surf Lambert decal:add alpha:blend


但这样就不是add的效果,并且最终结果呈现的也是不对的——到一定距离应该完全透明掉,而不是保持一个透明度在换mipmap。


于是。。。

#pragma surface surf Lambert decal:add alpha:add


这样也是不对的

同样的问题也出现在下面这个。

6.decal:blend

#pragma surface surf Lambert decal:blend


最终出现的结果跟我预想的不太一样。我只好搬出官方的例子了

Shader "Example/Decal" {
  Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
  }
  SubShader {
    Tags { "RenderType"="Opaque" "Queue"="Geometry+1" "ForceNoShadowCasting"="True" }
    LOD 200
    Offset -1, -1
    
    CGPROGRAM
    #pragma surface surf Lambert decal:blend
    
    sampler2D _MainTex;
    
    struct Input {
      float2 uv_MainTex;
    };
    
    void surf (Input IN, inout SurfaceOutput o) {
        half4 c = tex2D (_MainTex, IN.uv_MainTex);
        o.Albedo = c.rgb;
        o.Alpha = c.a;
      }
    ENDCG
    }
}

演示的结果给我测试的结果差不多。可能unity这个api的作用就是这样的吧。。是的,就这么一句稀里糊涂地糊弄了过去 。。。


再来看一下Custom modifier functions

一共四个

vertex:VertexFunction

finalcolor:ColorFunction

finalgbuffer:ColorFunction - Custom deferred path for altering gbuffer content.

finalprepass:ColorFunction - Custom prepass base path.

最后这两个官方很敷衍的直接跳过了。。。我也查不到这个资料。等看到terrain的shader的时候再来说这两个吧

第一二个就不说什么了吧,上个官方的例子看一下就知道了

1.vertex:VertexFunction

  Shader "Example/Normal Extrusion" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Amount ("Extrusion Amount", Range(-1,1)) = 0.5
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert vertex:vert
      struct Input {
          float2 uv_MainTex;
      };
      float _Amount;
      void vert (inout appdata_full v) {
          v.vertex.xyz += v.normal * _Amount;
      }
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

2.finalcolor:ColorFunction

  Shader "Example/Tint Final Color" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _ColorTint ("Tint", Color) = (1.0, 0.6, 0.6, 1.0)
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert finalcolor:mycolor
      struct Input {
          float2 uv_MainTex;
      };
      fixed4 _ColorTint;
      void mycolor (Input IN, SurfaceOutput o, inout fixed4 color)
      {
          color *= _ColorTint;
      }
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
           o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }
接下来看一下Shadows and Tessellation

1.addshadow

这个已经说过一点点了。。

如果没有这个addshadow指令的话。。

#pragma surface surf Lambert alpha

阴影也是有的。(注意一下我用了alpha)

如果

#pragma surface surf Lambert alpha addshadow

是的,没有任何变化,

为啥没有变化,其实很简单,这一套mobileshader就是个优化版本的。所以他去掉了对alphatest部分的shadow的支持,

也不能这么说。。。毕竟

#pragma surface surf Lambert alphatest:_Cutoff addshadow

还是有正确的阴影的效果的。这就要去查shadow部分的生成处理了。有点偏离文章的主题,暂且搁置。

#pragma surface surf Lambert alpha

然后修改

Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"

这样的话就可以让阴影部分正确的去显示。但是并不建议自己这么瞎改。希望能自己魔改一下整个shader,然后搭建一套属于自己的系统。

2.fullforwardshadows

这个我只说一下意思吧,就是在所有的可以产生阴影的灯光下,生成对应的阴影。

3.tessellate:TessFunction

细分曲面shader部分先忽略,毕竟是DX的东西,我做移动端一时半会还用不到,把这部分放到最最最后面吧

再接下来看一下Code generation options

1.exclude_path:deferred, exclude_path:forward, exclude_path:prepass

#pragma surface surf Lambert alpha exclude_path:deferred exclude_path:prepass

只有标注了这些,就不会在去生成相对应渲染路径的shader,可以让shader的变种少一些,设备会高兴的。

2.noshadow 不要影子

3.noambient 环境光不参与运算

4.novertexlights  在Forward渲染路径下不在应用顶点光照。

5.nolightmap 移除shader中对静态烘焙的光照贴图的支持。

6.nodynlightmap  shader不在支持实时GI
7.nodirlightmap  shader不再支持 directional lightmaps

8.nofog 不在支持系统的雾效

9.nometa 不在上次meta的pass(这个pass被用作“光照贴图和动态全局照明提取表面信息“)

10.noforwardadd 去除Foward路径下的additive pass部分,这样的话,这个shader只会支持一个直线光,其他的光都会去做顶点光照。

11.nolppv 移除 Light Probe Proxy Volume在shader的支持

12.noshadowmask 这个shader不在受 ShadowmaskDistance Shadowmask的影响。

关于shadowmask部分留在单独的shadow部分吧。

最后看一下Miscellaneous options

1.softvegetation 一旦写上了这个,就摊上了大事了,只有Soft Vegetation这个是On的时候,这个shader才会渲染。

2.interpolateview 用上了这个神器,就会把view Direction的计算从pixel shader部分搬到了vertex shader部分,这样就减少了pixel shader部分的运算。但是副作用即使多用一个纹理寄存器。

3.halfasview 在光照公式里用H(半角向量)去代替V(视角向量),H的计算是在vertexshader中进行的,并会自动normalized。

4.approxview 这个在unity5.0中已经移除了,请使用interpolateview
5.dualforward  Use dual lightmaps in forward rendering path.
6.dithercrossfade 使shader支持dithering effects。You can then apply this shader to GameObjects that use an LOD Group component configured for cross-fade transition mode.

猜你喜欢

转载自blog.csdn.net/u012871784/article/details/80651830
今日推荐