GLSL宏展开能做到这一点吗?

4
考虑以下GLSL函数:
float Pow3 (const in float f) {
    return f * f * f;
}

float Pow4 (const in float f) {
    return f * f * f * f;
}

float Pow5 (const in float f) {
    return f * f * f * f * f;
}

......等等。 有没有一种方法可以#define一个GLSL宏,该宏可以在编译时生成nf自乘的结果,而不使用内置的GLSL pow()函数呢?


1
你为什么“当然”不使用内置的 pow() 函数? - dbr
标准内置函数(例如'pow')经过优化,应该比自定义版本更快一些。 - fen
3
这只是我的问题的一个例子,与pow()无关。我想应该使用"f/f/f/f"代替... - metaleap
嗨Fen,你是说pow(5, 4)比5 * 5 * 5 * 5更优化?我并不是特别担心我的pow()调用本身——再次强调,如果我想在没有循环的情况下进行除法。或者做一些更复杂的事情。正如我所提到的,这是一个关于GLSL宏系统是否能够写出具有n个操作数的算术运算的通用问题(如果可以,那么如何)。话虽如此,在一个全屏四边形着色器中,需要处理超过200万个片段,每秒钟>60x进行大量计算,每个微小的优化差异都很重要,所有这些都会累加起来。 - metaleap
递归宏可以实现这一点,如果GLSL支持的话。 - undefined
1个回答

11

GLSL预处理器与标准C预处理器相似。实际上,您可以通过以下预处理器定义来实现所需的目标:

#define POW(a, b) Pow ## b ## (a)

请注意,由于连接运算符(##)仅从GLSL 1.30开始提供。实际上,在使用早期的GLSL版本时,此宏将生成编译器错误。

仍然在想为什么不使用pow函数...


1
谢谢!如上所述,这只是我的问题的一个示例,与pow()无关。例如,应该使用“f / f / f / f”。现在,在上面的宏中根本看不到*运算符。它被命名为POW并调用“Pow”吗?还是这是一种内置的宏语言“函数”? - metaleap
哦,我明白了。如果我给b=4和a=5,它会扩展成调用Pow4(5)。很好,但我仍然需要手动定义Pow4,对吧?这就是我想避免的——寻找一种让宏系统写出5 * 5 * 5 * 5以代替POW(5, 4)的方法。再次强调,这只是一个例子,不是关于pow()本身的问题 :) - metaleap
如果是这样,你就没那么幸运了。使用循环编写这些操作序列:通常这种类型的循环会被编译器展开。 - Luca
1
我认为 #define POW(a,b) ({ int c; float t=a; for(c=1;c<b;c++)t*=a; t;}) 也可以工作,而且不需要定义。虽然我没有测试过它。它要求一个块返回一个值(在c中是正确的,在glsl上也是如此)。所以它是可行的。请注意,循环已经展开了,因此它在功能上等同于递归尾调用优化函数或递归展开的宏。请注意,定义包含一个块,并且c是局部变量。最后一条语句返回块的值。再次强调,我没有测试过它。 - DDS
2
抱歉,没有前置内容。但是双引号等于号未定义。我们无法知道你用“equals”指的是什么。如果你的意思是“除了可变宏展开之外相等”,请写明。我被答案误导以为__VA_ARGS__实际上是可能的。 - johannes_lalala
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接