
obs-shaderfilter预处理宏进阶#include复用代码与USE_PM_ALPHA的正确用法【免费下载链接】obs-shaderfilterOBS Studio filter for applying an arbitrary shader to a source.项目地址: https://gitcode.com/gh_mirrors/ob/obs-shaderfilterobs-shaderfilter 是 OBS Studio 上非常受欢迎的着色器滤镜插件它允许你在任意源上加载自定义 shader实现投影、模糊、特效等无数玩法。很多新手在写 shader 时会遇到两件事一是重复代码越写越多二是颜色发灰发白怎么调都不对。本文就带大家进阶掌握obs-shaderfilter 预处理宏的两大核心技能用#include复用代码以及正确理解和使用USE_PM_ALPHA让你的 OBS shader 开发事半功倍。一、预处理宏是什么先认识三种宏指令obs-shaderfilter 在把 shader 文本交给编译器之前会先做一层预处理也就是对文本进行展开和替换。它支持三种宏指令指令作用一句话总结#define 名称 值定义常量或函数别名全文替换免去重复书写#include 路径插入另一个文件的内容公共代码写一次到处复用#define USE_PM_ALPHA 1关闭插件的预乘 alpha 自动校正专为老式 shader 准备这三个指令都写在 shader 文件的顶部。注意#define行不要以分号结尾这与普通 HLSL 语句不同。官方文档对此有明确说明见 README.md 中的 Optional Preprocessing Macros 章节。二、#define 宏让 shader 代码更清爽的捷径#define是最高频使用的宏。它把某个名字替换成后面的内容既可以是常量也可以是简单的函数片段。比如项目自带的 clock_analog.shader 就用它定义了圆周率#define PI 3.141592653589793238462643383 #define mod(x,y) (x - y * floor(x / y))之后你就可以直接写PI代替那串冗长的数字。另一个经典用法是把 GLSL 语法转成 OBS 的 HLSL项目自带的 filter_template.shader 里就有现成的一整套#define vec2 float2 #define vec3 float3 #define vec4 float4 #define fract frac #define mix lerp这样你在 Shadertoy 上看到的 GLSL 代码几乎可以原样搬进 OBS省去大量手动改写三、#include 复用代码把公共函数抽成独立文件当你写了几个 shader 之后一定会发现某些工具函数比如噪声、颜色转换、平滑过渡在每个文件里都要粘贴一遍。这时候就该用#include了。3.1 基本写法与路径规则在 shader 文件顶部写#include util-fns.effect插件在编译前会把该文件的内容原样插入到当前 shader 中。重点来了#include的路径是相对当前 shader 文件所在目录解析的而不是相对 OBS 安装目录或项目根目录。所以你最好把公共文件和你自己的 shader 放在同一个文件夹里方便管理。如果你在滤镜属性里直接输入 shader 文本不通过文件加载那么#include会找不到相对路径——因为它没有所在目录。所以使用#include时务必通过文件方式加载 shader这是最常见的坑之一。3.2 插件是如何处理 #include 的它的实现逻辑很直观逐行扫描 shader 文本凡是遇到#include开头的行就读取目标文件内容插入进来插入完成后递归继续处理被包含文件里的#include也就是支持嵌套包含。核心代码在 obs-shaderfilter.c 的load_shader_from_file函数约第 282–337 行。简单示意如下// 主文件 main.shader #include utils.effect // 会被展开成 utils 的全部内容 float4 mainImage(...) { ... }展开后插件实际编译的是拼接后的完整文本效果等同于你把公共函数直接粘贴进来。四、USE_PM_ALPHA 的正确用法解决颜色发灰发白这是很多新手最容易困惑的宏因为它涉及预乘 alphapre-multiplied alpha这个图形学概念。4.1 为什么颜色会发灰OBS 内部传递的画面是预乘 alpha格式即颜色通道已经乘过 alpha 值。如果你在 shader 里直接采样image并当作普通颜色使用比如想读出原始 RGB得到的结果会偏暗、偏灰特别是半透明区域。为了修正这一点obs-shaderfilter默认会自动做一次去预乘处理使用 OBS 的DrawAlphaDivide技术把颜色还原成非预乘空间保证你拿到的颜色是正常的。4.2 什么时候才需要手动开启插件默认已经修正了为什么还要#define USE_PM_ALPHA 1因为有些老式 shader 自己已经做了去预乘处理。如果插件再帮它去预乘一次就变成了双重校正颜色反而会出错。所以规则很简单✅ 你的 shader 直接使用image.Sample(...)拿颜色做普通运算 →不要加USE_PM_ALPHA让插件帮你校正。✅ 你写的是老式 shader代码里自己处理了预乘 alpha例如手动除以 alpha、或乘回 alpha→ 在顶部加上#define USE_PM_ALPHA 1关掉插件的自动校正。4.3 插件是怎么检测的插件在拼接完 shader 文本后会用字符串查找检测文本中是否存在#define USE_PM_ALPHA 1存在则跳过自动校正见 obs-shaderfilter.c 第 543–547 行并在渲染输入时改用普通Draw技术而非DrawAlphaDivide见同文件第 2922–2930 行。⚠️ 注意检测的是精确文本#define USE_PM_ALPHA 1所以请原样书写不要改动空格或数值。五、实战组合三个宏一起用假设我们想写一个带柔边的圆形遮罩效果可以这样组织文件结构my-filters/ ├── utils.effect # 公共函数库 ├── circle-mask.shader # 主 shaderutils.effect里放公共函数#define PI 3.14159265359 float2 uv_pi(float2 uv) { return uv * uv_pixel_interval; }circle-mask.shader顶部这样写#include utils.effect // 如果你的 shader 自行处理了预乘 alpha再取消下一行注释 // #define USE_PM_ALPHA 1这样既复用了公共代码又明确了 alpha 处理策略。项目里类似的圆角、圆环、边框类示例如 circle.shader、rounded_rect.shader都值得参考。六、常见问题速查Q1加了#include后画面全黑日志报找不到文件A路径是相对 shader 文件所在目录的检查公共文件是否放在同一目录文件名和大小写是否一致。Q2#define后编译报错A检查宏定义行末尾是否误加了分号;插件不支持带分号的宏。Q3开启USE_PM_ALPHA后颜色反而怪怪的A说明你的 shader 并没有自己做去预乘属于双重校正把该宏删掉即可。Q4嵌套#include会导致无限递归吗A目前实现是递归展开的请避免文件 A 包含 B、B 又包含 A 的循环引用否则会无限递归。七、总结掌握 obs-shaderfilter 的预处理宏你的 shader 开发效率会明显提升用#define定义常量和语法别名用#include把公共代码抽成可复用的独立文件用USE_PM_ALPHA正确处理预乘 alpha 避免颜色失真。结合项目自带的数十个示例 shader位于data/examples/目录边看边练很快你也能写出专业级的 OBS 特效滤镜。【免费下载链接】obs-shaderfilterOBS Studio filter for applying an arbitrary shader to a source.项目地址: https://gitcode.com/gh_mirrors/ob/obs-shaderfilter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考