Я просто реализовал некоторую интерполированную выборку текстур путем выборки ближайших пикселей 4x4, затем выполняя интерполяцию Лагранжа по оси x, чтобы получить четыре значения для использования интерполяции Лагранжа по оси y.
Это то же самое, что и бикубическая интерполяция, или она отличается? Или существуют разные виды бикубической интерполяции, и, возможно, это только одна из них?
Реализация Webgl Shadertoy здесь и соответствующий код GLSL (WebGL) ниже: https://www.shadertoy.com/view/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);
}
texture
interpolation
Алан Вульф
источник
источник
Ответы:
Оказывается, что нет, хотя вы можете использовать бикубическую интерполяцию Лагранжа для бикубической выборки текстур, это не самый качественный вариант и, вероятно, вряд ли будет использоваться.
Кубические сплайны Эрмита - лучший инструмент для работы.
Лагранжева интерполяция создаст кривую, которая проходит через точки данных, тем самым сохраняя непрерывность C0, но сплайны Эрмита сохраняют производные по краям, а также проходят через точки данных, сохраняя тем самым непрерывность C1 и выглядя намного лучше.
Этот вопрос содержит полезную информацию о кубических сплайнах Эрмита: /signals/18265/bicubic-interpolation
Вот кодовая версия кода, которую я разместил в вопросе:
Вот изображение, показывающее разницу между методами выборки. Слева направо: Ближайший сосед, Билинейный, Бикубический Лагранжа, Бикубический Эрмита
источник