Shader编程模块化开发方法分享

创建一个.cginc后缀的cg文件,保存我们要复用的代码

文件创建好以后,在shader文件里用#include"xxx.cginc"的方法,去插入它。

有一点需要注意的,就是最好在我们自己建的。cginc文件的顶部创建一个宏出来,例:

#ifndef MY_INCLUDE
#define MY_INCLUDE
// 你的cg代码内容
#endif

稍微对c++有点了解的人应该就会知道了,这在c++里是为了防止#include命令在我们的代码中反复插入相同的一段代码,造成不必要的浪费。

#ifndef会判断当前宏是否存在,如果没存在的话用#define创建该宏,#endif是设置了会起作用的代码范围。

外加使用#include时要写相对路径,例:#include"./xxx/xxx.cginc"./就是上一层目录的意思

用#define创建宏,来在shader中进行判断

这其实是上面方法的延伸,我们可以把方法创建成这个样子,例:

fixed4 MyCompute(fixed4 left, fixed4 right)
{
    fixed4 result = fixed4(0);
    #ifdef ADD_COMPUTE
    result = left + right;
    #elif
    result = left * right;
    #endif
    return result;
}

这段代码中我们有一步判断,如果存在宏ADD_COMPUTE,则进行加法,否则进行乘法。

我们在将这个文件#include之后,在调用这个方法时,如果想要进行加法的话,就可以在shader中直接创建这个宏就可以了,例:#defineADD_COMPUTE

好处:

  1. 是为一些不能传入参数的方法提供了做判断的手段,例如surfaceshader的内置光照函数,它们的结构是定死的,不允许增加参数。
  2. 是#ifdef这种,属于编译命令,是在编译阶段进行的判断,也就是说分支部分不会被编译到最终程序中,所以在运行的时候,就不存在任何的判断性能消耗了

还有一种特殊的写法,用CGINCLUDE……ENDCG块包围的代码

代码结构大概是这个样子的:

大家应该看出来了吧,CGINCLUDE……ENDCG块可以把cg代码写在SubShader{}的外面!

Shader "Z_TestShader/XXX"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    CGINCLUDE
    #include "UnityCG.cginc"
    uniform sampler2D _MainTex;
    struct appdata_t
    {
        float4 vertex : POSITION;
        half2 texcoord : TEXCOORD0;
    };
    struct v2f
    {
        float4 vertex : SV_POSITION;
        half2 texcoord : TEXCOORD0;
    };
    v2f vert (appdata_t v)
    {
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        o.texcoord = v.texcoord;
        return o;
    }
    fixed4 frag (v2f i) : COLOR
    {
        fixed4 col = tex2D(_MainTex , i.texcoord);
        fixed4 lum = Luminance(col);
        return lum;
    }
    ENDCG
    SubShader
    {
        ZTest Always  ZWrite Off Cull Off Blend Off
        Fog { Mode off } 
        Pass
        { 
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma fragmentoption ARB_precision_hint_fastest 
            ENDCG    
        }
    }
}

CGINCLUDE里定义的方法,都是可以在下面创建的pass中被引用的,所以在下面的pass里直接#pragmavertexvert,#pragmafragmentfrag指定了方法,直接让这个pass只剩下3句话了。

以上就是一些在shader里进行模块化开发的小技巧和写法,大家根据自己的情况来进行使用。

记住方法只是一种工具,想要发挥它的作用,主要还是看人是怎么用的。

猜你喜欢

转载自blog.csdn.net/qq826364410/article/details/81745021