【问题标题】:Second order functions in GLSL?GLSL 中的二阶函数?
【发布时间】:2012-03-19 00:28:47
【问题描述】:

我正在寻找一种将函数用作 GLSL 中另一个函数的参数的方法。在常规 C 中,可以通过将函数指针作为函数参数传递来模拟它。似乎其他语言(如 HLSL)现在也提供了处理高级构造(如高阶函数)的方法,或者可以使用 clever use of HLSL structures 模拟它们。不幸的是,我现在被 GLSL 困住了,我找不到任何方法来模拟高阶函数。当前(4.2)GLSL真的不可能吗?还是我错过了一些巧妙的技巧?

我正在努力实现的常见示例:

int f(someType f2, int i) {
    return f2(i);
}

【问题讨论】:

  • 而您需要在着色器中使用这种(可能成本高昂)间接来实现...?
  • 除了这种抽象会很好用之外,我遇到的实际问题如下:我有一个函数 f 可以切换参数 p(比如说,一个 int),并调用另一个函数 f2,其性质取决于切换值。能够将 f2 作为参数传递将允许我直接调用而无需切换,因为在我的应用程序的上下文中,我确切地知道在调用 f 本身时要在 f 中调用什么函数。我真的不知道这是否可能,也不知道要花多少钱,但我认为进行 100 箱切换可能会更糟。

标签: struct pass-by-reference glsl higher-order-functions


【解决方案1】:

GLSL 中没有高阶函数,但可以模拟它们:

#define second_order 1
#define second_order1 2
#define another_function 3
//there are no function pointers in GLSL, so I use integers instead

int call(int f2,int param1){
    //instead of a function, an integer is passed as a parameter
    switch(f2){
        case second_order:
            return param1*2;
        case second_order1:
            return param1*3;
    }
}

int call(int f2,int param1,int param2){
    //this function can be overloaded to accept more parameters
    switch(f2){
        case another_function:
            return param1 + param2;
    }
}

int f(int f2, int i) {
    return call(f2,i);
}

或者,这可以使用结构来完成:

struct function{
    int x;
};
function Sin(){
    return function(1);
}
function Cos(){
    return function(2);
}
float call(function func,float x){
    if(func == Sin()){
        return sin(x);
    }
    else if(func == Cos()){
        return cos(x);
    }
}

vec4 map(function func,vec4 a1){
    //this function can be overloaded for different array sizes
    vec4 a2;
    for(int i = 0; i < 4; i++){
        a2[i] = call(func,a1[i]);
    }
    return a2;
}

也可以使用宏来模拟通用二阶函数:

#define map(function,input1,output1) \
for(int i = 0; i < input1.length(); i++){ \
    output1[i] = function(input1[i]); \
}

此宏可用于任何类型的数组:

float[] arr1 = float[](1.,3.,4.);
float[arr1.length()] output1;
map(sin,arr1,output1)

【讨论】:

    【解决方案2】:

    我正在寻找一种将函数用作 GLSL 中另一个函数的参数的方法。

    简短的回答:你不能。

    在 GLSL 中最接近这种功能的是shader subroutines。而且这只允许外部 OpenGL API 选择要使用的子程序,而不是着色器本身。

    所以只需执行switch/case 声明并完成它。

    【讨论】:

    • 感谢您的建议。然而,让我感到震惊的是,GLSL 无法提供比无指针 C 更高级别的构造...
    • @AlexRepain:GLSL 必须在甚至不支持 recursion 的环境中运行。为什么希望函数指针起作用?
    • 我不希望函数指针起作用,我在问是否有解决方法。此外,我本身并不真的需要递归,我只是在寻找一些回调传递。事实上,它可能会形成一个递归,然后在我的脸上爆炸,这是一个可以接受的副作用。另外,如果环境可以处理“while”,我不明白为什么环境根本无法处理递归(想想尾调用递归)......
    • @AlexRepain:我的意思不是递归会影响你想要的。我的观点是,如果 GLSL 执行环境是如此静态以至于它甚至不允许递归,那么期望它允许选择哪个函数来动态运行是不合理的。着色器非常静态。大多数功能甚至都不存在;他们被内联了。
    • 公平点。我想如果提供了一种在运行时选择函数的语法方式,那么无论如何它都会归结为内联的 switch 语句。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-02-13
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 2012-05-15
    相关资源
    最近更新 更多