Szukam sposobu na użycie funkcji jako argumentu do innej funkcji w GLSL. W zwykłym C można to zasymulować, przekazując wskaźnik funkcji jako argument funkcji. Wydaje się również, że inne języki (takie jak HLSL) zapewniają teraz sposoby radzenia sobie z konstrukcjami wysokiego poziomu, takimi jak funkcje wyższego rzędu, lub mogą je symulować za pomocą sprytne wykorzystanie struktur HLSL. niestety na razie utknąłem z GLSL i nie mogę znaleźć sposobu na symulację funkcji wyższego rzędu. Czy to naprawdę niemożliwe w obecnym (4.2) GLSL? A może brakuje mi jakiejś sprytnej sztuczki?

Typowy przykład tego, co staram się osiągnąć:

int f(someType f2, int i) {
    return f2(i);
}
7
Alex Repain 29 luty 2012, 18:01

2 odpowiedzi

Najlepsza odpowiedź

Szukam sposobu na użycie funkcji jako argumentu do innej funkcji w GLSL.

Krótka odpowiedź: Nie możesz.

Najbliżej tego rodzaju funkcjonalności, którą uzyskasz w GLSL, są podprogramy cieniowania. A to pozwala tylko zewnętrznemu API OpenGL wybrać podprogram do użycia, a nie sam moduł cieniujący.

Więc po prostu zrób instrukcję switch/case i skończ z tym.

5
Nicol Bolas 29 luty 2012, 21:36

W GLSL nie ma funkcji wyższego rzędu, ale można je symulować:

#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);
}

Alternatywnie można to zrobić za pomocą struktur:

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;
}

Możliwe jest również symulowanie ogólnych funkcji drugiego rzędu za pomocą makr:

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

To makro może być używane z dowolnym typem tablicy:

float[] arr1 = float[](1.,3.,4.);
float[arr1.length()] output1;
map(sin,arr1,output1)
0
Anderson Green 10 lipiec 2021, 03:15