Ich habe gerade eine interpolierte Texturabtastung implementiert, indem ich die nächstgelegenen 4x4-Pixel abgetastet und dann eine Lagrange-Interpolation über die x-Achse durchgeführt habe, um vier Werte für die Verwendung der Lagrange-Interpolation über die y-Achse zu erhalten.
Ist das dasselbe wie bikubische Interpolation oder ist es anders? Oder gibt es verschiedene Arten der bikubischen Interpolation, und dies ist vielleicht nur eine davon?
Webgl Shadertoy-Implementierung hier und relevanter GLSL (WebGL) -Code unten: https://www.shadertoy.com/view/MllSzX
Vielen Dank!
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);
}
texture
interpolation
Alan Wolfe
quelle
quelle
Antworten:
Es stellt sich heraus, dass Sie zwar die bikubische Lagrange-Interpolation für die Abtastung von bikubischen Texturen verwenden können, diese jedoch nicht die Option mit der höchsten Qualität ist und wahrscheinlich auch nicht verwendet wird.
Kubische Einsiedlerkeile sind ein besseres Werkzeug für den Job.
Durch die Lagrange-Interpolation wird eine Kurve erstellt, die durch die Datenpunkte verläuft, wodurch die C0-Kontinuität erhalten bleibt. Hermite-Splines bewahren jedoch die Ableitungen an den Rändern, während sie gleichzeitig durch die Datenpunkte verlaufen, wodurch die C1-Kontinuität erhalten bleibt und viel besser aussieht.
Diese Frage enthält einige nützliche Informationen zu kubischen Einsiedler-Splines: /signals/18265/bicubic-interpolation
Hier ist die kubische Einsiedlerversion des Codes, den ich in der Frage gepostet habe:
Hier ist ein Bild, das den Unterschied zwischen den Probenahmemethoden zeigt. Von links nach rechts: Nächster Nachbar, Bilinear, Lagrange Bicubic, Hermite Bicubic
quelle