我只是通过对4x4最近的像素进行采样,然后在x轴上进行Lagrange插值来获取四个值,以便在y轴上使用Lagrange插值来实现一些插值纹理采样。

与双三次插值相同还是不同?还是有不同种类的双三次插值,也许只是其中之一? / MllSzX

谢谢!

 float c_textureSize = 64.0;

float c_onePixel = 1.0 / c_textureSize;
float c_twoPixels = 2.0 / c_textureSize;

float c_x0 = -1.0;
float c_x1 =  0.0;
float c_x2 =  1.0;
float c_x3 =  2.0;

//=======================================================================================
vec3 CubicLagrange (vec3 A, vec3 B, vec3 C, vec3 D, float t)
{
    return
        A * 
        (
            (t - c_x1) / (c_x0 - c_x1) * 
            (t - c_x2) / (c_x0 - c_x2) *
            (t - c_x3) / (c_x0 - c_x3)
        ) +
        B * 
        (
            (t - c_x0) / (c_x1 - c_x0) * 
            (t - c_x2) / (c_x1 - c_x2) *
            (t - c_x3) / (c_x1 - c_x3)
        ) +
        C * 
        (
            (t - c_x0) / (c_x2 - c_x0) * 
            (t - c_x1) / (c_x2 - c_x1) *
            (t - c_x3) / (c_x2 - c_x3)
        ) +       
        D * 
        (
            (t - c_x0) / (c_x3 - c_x0) * 
            (t - c_x1) / (c_x3 - c_x1) *
            (t - c_x2) / (c_x3 - c_x2)
        );
}

//=======================================================================================
vec3 BicubicTextureSample (vec2 P)
{
    vec2 pixel = P * c_textureSize + 0.5;

    vec2 frac = fract(pixel);
    pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);

    vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;
    vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;
    vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;
    vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;

    vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;
    vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;
    vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;
    vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    

    vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;
    vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;
    vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;
    vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    

    vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;
    vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;
    vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;
    vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    

    vec3 CP0X = CubicLagrange(C00, C10, C20, C30, frac.x);
    vec3 CP1X = CubicLagrange(C01, C11, C21, C31, frac.x);
    vec3 CP2X = CubicLagrange(C02, C12, C22, C32, frac.x);
    vec3 CP3X = CubicLagrange(C03, C13, C23, C33, frac.x);

    return CubicLagrange(CP0X, CP1X, CP2X, CP3X, frac.y);
}
 


评论

如果发生bitrot,您可以在此处发布相关的着色器代码,不是吗?

我们应该为着色器代码添加一些更漂亮的代码标记,如果有人没有击败我,我会在meta上发布!

语法突出显示覆盖的语言列表中没有特定的着色器语言吗?

我不确定。这只是GLSL(确切地说是从webgl!)。我在每一行代码之前只做了4个空格,不确定是否有更好的方法对其进行标记...

#1 楼

事实证明,不可以,尽管可以将双三次Lagrange插值用于双三次纹理采样,但这不是最高质量的选择,并且可能实际上不太可能使用。
拉格朗日插值法将使一条曲线穿过数据点,从而保留C0连续性,但Hermite样条曲线保留边沿的导数,同时也穿过数据点,从而保留C1的连续性并看起来更好。

这个问题有一些关于三次厄米样条的信息: >
这是我在问题中发布的代码的三次方Hermite版本:
此图显示了采样方法之间的差异。从左至右:最近邻,双线性,Lagrange Bicubic,Hermite Bicubic



评论


$ \ begingroup $
尽管从某种意义上说,所有三次样条都是等效的,但从概念上讲,使用Catmull-Rom样条可能更容易。例如cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
$ \ endgroup $
–西蒙F
2015年8月5日14:51

$ \ begingroup $
在这种情况下,您认为tau参数是有用还是不利?我可能是错的,但是我觉得catmull rom太“用户定义”了(必须进行调整),而hermite样条曲线试图仅使用那里数据的信息。看来立方埃尔米特似乎更接近“基本事实”,我想这就像是理想的Sinc滤波器。你觉得呢
$ \ endgroup $
–艾伦·沃尔夫(Alan Wolfe)
15年8月5日在15:57

$ \ begingroup $
我看不到Catmull-Rom是“用户定义的”。一旦具有4个连续点的序列,即P [i-1],P [i],P [i + 1],P [i + 2](对于2D情况为4x4),则曲线段将在P [i ]和P [i + 1],并且C1与相邻段连续。 Sinc滤波器适用于音频,但不适用于视频。参见Mitchell和Netravali:cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/…IIRC Catmull-Rom是他们提出的滤波器系列的特例,但我认为滤波器是一个近似曲线,与CR不同,它可能无法通过原始说明。
$ \ endgroup $
–西蒙F
15年8月6日在9:24

$ \ begingroup $
这就是他的hermite样条曲线的工作方式,除了catmull rom样条曲线具有用户定义的附加参数tau(张力)。另外,sinc确实适用于视频,DSP是DSP:P
$ \ endgroup $
–艾伦·沃尔夫(Alan Wolfe)
15年8月6日在14:04

$ \ begingroup $
我必须承认,我以前从未见过与Catmull Rom花键相关的张力参数,但后来我真的只通过Foley&van Dam(et al)或例如Watt&Watt了解了它们,AFAICR,别提这样的事情。话虽如此,实际上,有四个约束条件-即曲线必须经过2个点,并且在这些点处有两个定义的切线**,并且是三次方-我对如何使用任何点有些困惑支持张力参数的自由度更高.... **除非您的意思是切线可以缩放?
$ \ endgroup $
–西蒙F
15年8月6日在14:29