unityshader中经常见到CGPROGRAM,除此之外还有一个CGINCLUDE关键字。 二个关键字都是用ENDCG来结束,但是用法完全不一样。

CGINCLUDE和ENDCG内可以插入一些shader代码,unity会把插入的这些代码插入到每一个pass中。这等于我们只在CGINCLUDE和ENDCG中写一次就可以在多个Pass里复用这些代码。

  如果多个Pass中顶点着色器和片元着色器计算的公式之类的都是一样的,只有渲染状态不一样,比如透明度混合的混合参数不同等,此时我们完全可以把多个Pass里重复的顶点计算和

片元计算写在CGINCLUDE和ENDCG内,复用这部分代码。下面放一个示例shader:

Shader "CGINCLUDEExample" {
  Properties {
    _Color ("Color", Color) = (1,1,1,1)
  }

CGINCLUDE
  #include "UnityCG.cginc"

  struct appdata_shaded {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
  };

  struct v2f_shaded {
    float4 vertex : SV_POSITION;
    float fresnelValue : TEXCOORD0;
  };

  v2f_shaded vert_shaded (appdata_shaded v) {
    v2f_shaded o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
    o.fresnelValue = lerp(0.39, 0.66, saturate(dot(v.normal, viewDir)));
    return o;
  }

  fixed4 _Color;

  fixed4 frag_shaded (v2f_shaded i) : SV_Target {
    return _Color * i.fresnelValue;
  }

ENDCG

  SubShader {    

    //Pass 1 : Shaded solid
    Pass {
      Blend One Zero
      ZWrite On
      ZTest On

      CGPROGRAM
        #pragma vertex vert_shaded
        #pragma fragment frag_shaded
      ENDCG
    }

    //Pass 2 : Shaded transparent
    Pass {
      Blend SrcAlpha OneMinusSrcAlpha
      ZWrite Off
      ZTest On

      CGPROGRAM
        #pragma vertex vert_shaded
        #pragma fragment frag_shaded
      ENDCG
    }
  }
}

在这个shader里,2个Pass都用了透明度混合,不过混合的参数不一样,但是顶点计算和片元计算都一样,所以把顶点函数vert_shaded和片元函数frag_shaded复用,写到CGINCLUDE和ENDCG里面。

这样就等于在Pass1和Pass2中都声明了顶点函数vert_shaded和片元函数frag_shaded。代码看起来简洁许多,复用代码也能使得我们减少手误敲错代码的几率,shader有改动时也只需改动一处即可。

  

05-11 20:03