【Unity ShaderShader】自定义CGInclude函数库 预编译

补充一些零碎的小知识点,为了提高效率我选择更快速的方法,直接引用他人写的不错的文章,复习的时候就可以直接查看啦!

1 自定义cginc工具库

unity 自定义shader cginc 函数工具库并引用

Unity内置有很多.cginc文件,都是自带的shader工具函数库,例如常用的Lighting.cginc、UnityCG.cginc等,shader中引用通常是在PASS中添加如下内容:

#include "UnityCG.cginc"

当我们想要自己自定函数工具库时,就要考虑何种格式、shader中如何使用的问题了。

1.1 创建文件

unity内部不能直接创建.cginc文件,文件夹下文件,更改后缀为.cginc

1.2 标准结构格式

#ifndef XXX

#define XXX

// 定义常用的宏、结构体、全局变量、函数等等

#endif

#ifndef 避免双重定义

当程序文件多了起来,容易出现文件被重复引用的情况,此时最好加上#ifdef #define和#endif,避免双重定义的错误,拿最近做庄懂赛博小人有个自定义的插值环境光.cginc文件为例:

#ifndef MY_CGINC

#define MY_CGINC

//插值环境光,三个颜色:顶up、侧side、底down

float3 TrinColAmbient (float3 n, float3 uCol, float sCol, float dCol) {

float uMask = max(0.0, n.g); // 获取朝上部分遮罩

float dMask = max(0.0, -n.g); // 获取朝下部分遮罩

float sMask = 1.0 - uMask - dMask; // 获取侧面部分遮罩

float3 envCol = uCol * uMask +

sCol * sMask +

dCol * dMask; // 混合环境颜色

return enCol;

}

#endif

#ifndef,if ! define,即“如果没定义xx”,整个预编译过程大概是:

如果没定义MY_CGINC这个宏的话,则条件为真,继续进行接下来直到#endif中间的内容,即定义MY_CGINC这个宏,并定义一个方法TrinColAmbient();如果定义过了这个宏,则条件为假,直接跳过内容,endif

1.3 使用

如果.cginc文件在当前shader的相同目录下,直接:

#include "MYcginc.cginc"

但一般我们创建的.cginc文件都会放在跟shader不同的文件目录下,此时就需要相对路径了:

#include "../cginc/Mycginc.cginc"

这里的../表示上一级目录,同样的../../表示上两级目录,具体关于相对路径可以看:什么是相对路径?相对路径的具体写法和用法

2 预编译处理

VS学习c语言笔记记录_九九345的博客-CSDN博客_vs语言符合模式

什么是相对路径?相对路径的具体写法和用法

既然涉及到了#ifndef、#define的内容,就顺便学习一下预编译处理这个概念。

2.1 基本概念

什么是?

预编译也可以叫做预处理,是做些代码文本的替换工作,处理#开头的指令,例如:

#include // 拷贝#include包含的文件代码

#define // 宏定义替换

什么时候开始?

预编译指令发生在程序正式开始编译前,但这个预编译本身可以放在程序的任何位置。

3种功能

宏定义

条件编译

包含文件

2.2 常见的编译指令

这里直接引用了文章避免头文件重复引入和重复定义中的汇总,侵删:

//条件编译

#define // 宏定义

#undef // 取消宏

#include // 文本包含

#ifdef // 如果宏被定义就进行编译

#if defined // 与ifdefine的区别在于可以可以组成复杂的判别条件

#ifndef // 如果宏未被定义就进行编译

#if !defined // 与if !define的区别在于可以可以组成复杂的判别条件

#endif // 结束编译块的控制

#if defined // 表达式非零就对代码进行编译

#else // 作为其他预处理的剩余选项进行编译

#elif // 这是一种#else和#if的组合选项

#elif defined // 与ifdefine的区别在于可以可以组成复杂的判别条件

#elif !defined // 与ifdefine的区别在于可以可以组成复杂的判别条件

//编译指令

#line // 改变当前的行数和文件名称

#error // 输出一个错误信息

#pragma // 为编译程序提供非常规的控制流信息,可跟once,message等许多参数。

2.3 #pragma once 指令

这个指令似乎没怎么见过,它的作用是:使同一个文件不会被包含多次,与上面提到的#ifndef相比更加方便了,遇到已经被引过的文件会直接跳过。但无法剔除不同的2个表达同一个物理意义的文件。

与#ifndef混用

#pragma once

#ifndef XXX

#define XXX

#endif

————————————————

版权声明:本文为CSDN博主「九九345」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_41835314/article/details/128835713

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值