注意:我是一名图形爱好者,日常工作中不使用Metal或C++!
关于展开答案的建议:由于Metal Shading Language是C++,因此您可以使用宏使得使用展开数组更加简便。
创建重复宏
重复代码并不美观,但只需要编写一次:
#define REP1(FN, ...) FN(0, ##__VA_ARGS__)
#define REP2(FN, ...) REP1(FN, ##__VA_ARGS__) FN(1, ##__VA_ARGS__)
#define REP3(FN, ...) REP2(FN, ##__VA_ARGS__) FN(2, ##__VA_ARGS__)
#define REP4(FN, ...) REP3(FN, ##__VA_ARGS__) FN(3, ##__VA_ARGS__)
#define REP5(FN, ...) REP4(FN, ##__VA_ARGS__) FN(4, ##__VA_ARGS__)
#define REP6(FN, ...) REP5(FN, ##__VA_ARGS__) FN(5, ##__VA_ARGS__)
#define REP7(FN, ...) REP6(FN, ##__VA_ARGS__) FN(6, ##__VA_ARGS__)
#define REP8(FN, ...) REP7(FN, ##__VA_ARGS__) FN(7, ##__VA_ARGS__)
#define REP9(FN, ...) REP8(FN, ##__VA_ARGS__) FN(8, ##__VA_ARGS__)
#define REP10(FN, ...) REP9(FN, ##__VA_ARGS__) FN(9, ##__VA_ARGS__)
#define REPEAT(N, ...) REP ## N(__VA_ARGS__)
声明数组
函数宏可以用于生成数组成员:
#define DECLARE_VAR(VAR_INDEX, VAR_TYPE, VAR_PREFIX) VAR_TYPE VAR_PREFIX ## VAR_INDEX;
struct FragmentIn {
float4 position [[position]];
REPEAT(10, DECLARE_VAR, float3, array)
};
这将扩展为:
struct FragmentIn {
float4 position [[position]];
float3 array0;
float3 array1;
float3 array2;
float3 array3;
float3 array4;
float3 array5;
float3 array6;
float3 array7;
float3 array8;
float3 array9;
};
访问数组
然后,您可以逐个访问未展开的数组元素,或编写另一个类似函数的宏来操作它们。以下示例对未展开的数组求和:
#define SUM_ARRAY(VAR_INDEX, VAR_PREFIX, TOTAL) TOTAL += VAR_PREFIX ## VAR_INDEX;
float3 sumOfVectors;
REPEAT(10, SUM_ARRAY, fragmentIn.array, sumOfVectors)
这会扩展为:
float3 sumOfVectors;
sumOfVectors += fragmentIn.array0;
sumOfVectors += fragmentIn.array1;
sumOfVectors += fragmentIn.array2;
sumOfVectors += fragmentIn.array3;
sumOfVectors += fragmentIn.array4;
sumOfVectors += fragmentIn.array5;
sumOfVectors += fragmentIn.array6;
sumOfVectors += fragmentIn.array7;
sumOfVectors += fragmentIn.array8;
sumOfVectors += fragmentIn.array9;