Wydajny Kod filtrujący Bicubic w GLSL?

Zastanawiam się, czy ktoś ma kompletny, działający i wydajny kod do filtrowania tekstur bicubic w glsl. Jest to:

Http://www.codeproject.com/Articles/236394/Bi-Cubic-and-Bi-Linear-Interpolation-with-GLSL lub https://github.com/visionworkbench/visionworkbench/blob/master/src/vw/GPU/Shaders/Interp/interpolation-bicubic.glsl

Ale oba robią 16 tekstur, gdzie tylko 4 są "required": {]}

Https://groups.google.com/forum/#! topic / comp. graphics. api. opengl / kqrujgJfTxo

Jednak powyższa metoda wykorzystuje brakującą funkcję " cubic ()", której Nie wiem Do czego ma ona służyć, a także pobiera niewyjaśniony parametr "texscale".

Jest też wersja Nvidii:

Http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter20.html

Ale wierzę, że wykorzystuje CUDA, które jest specyficzne dla kart Nvidii. Potrzebuję glsl.

Prawdopodobnie mógłbym przenieść wersję Nvidii na glsl, ale pomyślałem, że najpierw zapytam, Czy ktoś ma już kompletny, działający shader GLSL bicubic.

Author: Vern Jensen, 2012-11-21

7 answers

Postanowiłem poświęcić chwilę na wykopanie moich starych działań Perforce i znalazłem brakującą funkcję cubic (); enjoy! :)

vec4 cubic(float v)
{
    vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
    vec4 s = n * n * n;
    float x = s.x;
    float y = s.y - 4.0 * s.x;
    float z = s.z - 4.0 * s.y + 6.0 * s.x;
    float w = 6.0 - x - y - z;
    return vec4(x, y, z, w);
}
 7
Author: t0rakka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-21 13:32:36

Brakująca funkcja cubic() w odpowiedzi JAre może wyglądać tak:

vec4 cubic(float x)
{
    float x2 = x * x;
    float x3 = x2 * x;
    vec4 w;
    w.x =   -x3 + 3*x2 - 3*x + 1;
    w.y =  3*x3 - 6*x2       + 4;
    w.z = -3*x3 + 3*x2 + 3*x + 1;
    w.w =  x3;
    return w / 6.f;
}

Zwraca cztery wagi dla sześciennego B-splajnu.

Wszystko zostało wyjaśnione w NVIDIA Gems.
 6
Author: Maf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-15 13:28:03

(EDIT)

cubic spline

  • Texscale to współczynnik wielkości okna próbkowania. Możesz zacząć od wartości 1.0.

vec4 filter(sampler2D texture, vec2 texcoord, vec2 texscale)
{
    float fx = fract(texcoord.x);
    float fy = fract(texcoord.y);
    texcoord.x -= fx;
    texcoord.y -= fy;

    vec4 xcubic = cubic(fx);
    vec4 ycubic = cubic(fy);

    vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y -
0.5, texcoord.y + 1.5);
    vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x +
ycubic.y, ycubic.z + ycubic.w);
    vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) /
s;

    vec4 sample0 = texture2D(texture, vec2(offset.x, offset.z) *
texscale);
    vec4 sample1 = texture2D(texture, vec2(offset.y, offset.z) *
texscale);
    vec4 sample2 = texture2D(texture, vec2(offset.x, offset.w) *
texscale);
    vec4 sample3 = texture2D(texture, vec2(offset.y, offset.w) *
texscale);

    float sx = s.x / (s.x + s.y);
    float sy = s.z / (s.z + s.w);

    return mix(
        mix(sample3, sample2, sx),
        mix(sample1, sample0, sx), sy);
}

Źródło

 4
Author: JAre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-24 11:35:12

Wow. Rozpoznaję powyższy kod (nie mogę skomentować w / reputation

Myślałem o tym w ten sposób: OK, więc jeśli obsłużyć każdy quad (2x2) z filtrem liniowym pozostałym problemem jest to, czy wiersze i kolumny dzielą wagi? To był jedyny problem, jaki miałem na myśli, kiedy postanowiłem stworzyć kod. Oczywiście mogą być dzielone; wagi są takie same dla każdej kolumny i rzędu; idealne!

Teraz miałem cztery próbki. Pozostały problem polegał na tym, jak prawidłowo połączyć próbki. To była największa przeszkoda do pokonania. Zajęło to około 10 minut ołówkiem i papierem. Drżącymi dłońmi wpisałem kod i zadziałało, fajnie. Potem wgrałem binaria do gościa, który obiecał sprawdzić to na swoim T42 (?) i zgłosił, że działa. Koniec. :)

Mogę zapewnić, że równania sprawdzają się i dają matematycznie identyczne wyniki do obliczenia próbek indywidualnie. FYI: z procesorem szybsze jest samodzielne skanowanie poziome i pionowe. Z GPU wielokrotne przejścia nie jest to świetny pomysł, zwłaszcza, gdy to prawdopodobnie nie jest wykonalne i tak w typowym przypadku użycia.

Food for thought: możliwe jest użycie texture lookup dla funkcji cubic (). To, co jest szybsze zależy od GPU, ale ogólnie rzecz biorąc, próbnik jest lekki po stronie ALU, po prostu robiąc arytmetykę, zrównoważyłoby rzeczy. YMMV.

 4
Author: t0rakka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-21 10:34:26

Znalazłem tę implementację, która może być użyta jako zamiennik texture () (z http://www.java-gaming.org/index.php?topic=35123.0 (jedna literówka naprawiona)):

// from http://www.java-gaming.org/index.php?topic=35123.0
vec4 cubic(float v){
    vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
    vec4 s = n * n * n;
    float x = s.x;
    float y = s.y - 4.0 * s.x;
    float z = s.z - 4.0 * s.y + 6.0 * s.x;
    float w = 6.0 - x - y - z;
    return vec4(x, y, z, w) * (1.0/6.0);
}

vec4 textureBicubic(sampler2D sampler, vec2 texCoords){

   vec2 texSize = textureSize(sampler, 0);
   vec2 invTexSize = 1.0 / texSize;

   texCoords = texCoords * texSize - 0.5;


    vec2 fxy = fract(texCoords);
    texCoords -= fxy;

    vec4 xcubic = cubic(fxy.x);
    vec4 ycubic = cubic(fxy.y);

    vec4 c = texCoords.xxyy + vec2 (-0.5, +1.5).xyxy;

    vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
    vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s;

    offset *= invTexSize.xxyy;

    vec4 sample0 = texture(sampler, offset.xz);
    vec4 sample1 = texture(sampler, offset.yz);
    vec4 sample2 = texture(sampler, offset.xw);
    vec4 sample3 = texture(sampler, offset.yw);

    float sx = s.x / (s.x + s.y);
    float sy = s.z / (s.z + s.w);

    return mix(
       mix(sample3, sample2, sx), mix(sample1, sample0, sx)
    , sy);
}

Przykład: Nearest, bilinear, bicubic:

Tutaj wpisz opis obrazka

ImageData tego obrazu to

{{{0.698039, 0.996078, 0.262745}, {0., 0.266667, 1.}, {0.00392157, 
   0.25098, 0.996078}, {1., 0.65098, 0.}}, {{0.996078, 0.823529, 
   0.}, {0.498039, 0., 0.00392157}, {0.831373, 0.00392157, 
   0.00392157}, {0.956863, 0.972549, 0.00784314}}, {{0.909804, 
   0.00784314, 0.}, {0.87451, 0.996078, 0.0862745}, {0.196078, 
   0.992157, 0.760784}, {0.00392157, 0.00392157, 0.498039}}, {{1., 
   0.878431, 0.}, {0.588235, 0.00392157, 0.00392157}, {0.00392157, 
   0.0666667, 0.996078}, {0.996078, 0.517647, 0.}}}

Próbowałem to odtworzyć (wiele innych technik interpolacji)

Tutaj wpisz opis obrazka

Ale mają zaciśnięte wyściółki, podczas gdy ja mam powtarzające (owijanie) granice. Dlatego nie jest to dokładnie to samo.

Wygląda na to, że ten dwubiegunowy biznes nie jest poprawną interpolacją , tzn. nie przyjmuje pierwotnych wartości w punktach, w których dane są zdefiniowane.

 3
Author: masterxilo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-11 18:55:09

Dla wszystkich zainteresowanych kodem GLSL do wykonania tri - interpolacja sześcienna, kod odlewania promieni za pomocą interpolacji sześciennej można znaleźć w folderze examples / glCubicRayCast w: http://www.dannyruijters.nl/cubicinterpolation/CI.zip

Edit: sześcienny kod interpolacji jest teraz dostępny na GitHubie: CUDA version i WebGL version, oraz GLSL sample.

 2
Author: Danny Ruijters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-29 13:01:33

Używam receptury cubic Spline @Maf od ponad roku i polecam, jeśli cubic B-spline spełnia Twoje potrzeby.

Ale niedawno zdałem sobie sprawę, że dla mojego konkretnego zastosowania ważne jest, aby intensywności pasowały dokładnie w punktach próbkowania. Więc przełączyłem się na spline Catmull-Rom, który używa nieco innej receptury jak tak:

// Catmull-Rom spline actually passes through control points
vec4 cubic(float x) // cubic_catmullrom(float x)
{
    const float s = 0.5; // potentially adjustable parameter
    float x2 = x * x;
    float x3 = x2 * x;
    vec4 w;
    w.x =    -s*x3 +     2*s*x2 - s*x + 0;
    w.y = (2-s)*x3 +   (s-3)*x2       + 1;
    w.z = (s-2)*x3 + (3-2*s)*x2 + s*x + 0;
    w.w =     s*x3 -       s*x2       + 0;
    return w;
}

Znalazłem te współczynniki, plus te dla wielu innych smaków sześciennych splajnów, w notatkach do wykładu na: http://www.cs.cmu.edu/afs/cs/academic/class/15462-s10/www/lec-slides/lec06.pdf

 1
Author: Christopher Bruns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-18 18:35:55