最近又是一阵瞎忙,至于忙啥,忙工作,忙生活,然后现在想想有感觉是一瞬间的事情,好像只是过往云烟,吹之即散.
突然感觉做人真的应该学会留下点什么,哪怕是毫无意义的东西呢.
那么接着说,这次是学习多Pass的渲染,在shader的使用中会发现有时候只进行一次渲染是不够的,还要在它的基础上在加上一次或者多次才行,这就是多Pass的渲染的由来.
之前的shader使用都是基于surface shader 这样的unity内置表面渲染进行的,并没有出现过Pass,但是实际上但是实际上在执行的时候surface shader 是要转译成含有Pass的这样的CG/HLSL这样的语言的.
就像下面这种格式

Shader "Name"
{
  Properties
  {

  }

  SubShader
  {

    Tags{  }

    Pass

    {

    }

    Pass

    {

    }

  }

  FallBack "other"

}

现在我就来介绍一个实际的多Pass的列子.

unity 排序节点 unity多pass顺序_shader

这是一张热门游戏 暗黑破坏神3 的一张截图,被选中的蜘蛛(或者其他物体)会显示出它的轮廓 ,这里就用到了多Pass的渲染.

现在,给一个简单的物体轮廓的代码.

Shader"Outlined"
{
  Properties
  {
    _OutlineColor("Outline Color",Color) = (0,0,0,1)
    _Outline("Outline width",Range(0.0,0.03)) = 0.005
  }

  SubShader
  {
    Tags{ "Queue" = "Transparent" }

    Pass
    {
      Name "BASE"
      Cull Back 
      Blend Zero One 

      SetTexture[_OutlineColor]
      {
        ConstantColor(0,0,0,0)
        Combine constant 
      }

    }

    pass
    {
      Name"OUTLINE"
      Tags{"LightMode" = "Always"}
      Cull Front 

      Blend One OneMinusDstColor

      CGPROGRAM
      #pragma vertex vert 
      #pragma fragment frag 

      #include "UnityCG.cginc"

      struct appdata

      {
        float4 vertex : POSITION;
        float3 normal : NORMAL;

      };

      struct v2f

      {
        float4 pos :POSITION;
        float4 color : COLOR;

      };

      uniform float _Outline;
      uniform float4 _OutlineColor;

      v2f vert(appdata v)
      {
        v2f o;
        o.pos = mul(UNITY_MATRIX_MVP,v.vertex);

        float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV,v.normal);
        float2 offset = TransformViewToProjection(norm.xy);

        o.pos.xy += offset*o.pos.z* _Outline;
        o.color = _OutlineColor;

        return o;


      }

      half4 frag(v2f i):COLOR
      {
        return i.color;
      }
      ENDCG
    }

  }
  FallBack"Diffuse"
}

下面是效果图

unity 排序节点 unity多pass顺序_unity 排序节点_02

挂载到球形物体上后我们可以通过属性面板,调整它的轮廓的粗细以及颜色.

在这个shader中,使用了两个Pass ,第一个是固定管线的渲染方法,进行了背面剔除,同时也在深度缓冲区中留下了背面剔除的深度值,此时i可以想象一下,物体变成了什么样子.第二个用了正面剔除,那些经过法线伸展后的点会因为与深度剔除的缓存值比较后无法通过而被剔除,也就是说仅仅剩下正面与背面的边缘处因为伸展的原因保留了下来,于是轮廓就出现了,这就是大体过程了.

至于代码中的东西,就不用注释了,相信有基础的同学能很轻松的看明白.