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中直接创建这个宏就可以了,例:#define ADD_COMPUTE
好处:
1是为一些不能传入参数的方法提供了做判断的手段,例如surface shader的内置光照函数,它们的结构是定死的,不允许增加参数。
2是#ifdef这种,属于编译命令,是在编译阶段进行的判断,也就是说分支部分不会被编译到最终程序中,所以在运行的时候,就不存在任何的判断性能消耗了


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

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

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 ... ENDCG 块可以把cg代码写在 SubShader {} 的外面!
CGINCLUDE里定义的方法,都是可以在下面创建的pass中被引用的,所以在下面的pass里直接#pragma vertex vert#pragma fragment frag指定了方法,直接让这个pass只剩下3句话了。


以上就是一些在shader里进行模块化开发的小技巧和写法,大家根据自己的情况来进行使用。
记住方法只是一种工具,想要发挥它的作用,主要还是看人是怎么用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值