Фрагментные шейдеры на картах ATI и NVIDIA

Я использую этот шейдер fragent (вдохновленный некоторым учебником, найденным на сайте NVIDIA некоторое время назад). Он в основном вычисляет билинейную интерполяцию 2D текстуры.

uniform sampler2D myTexture;
uniform vec2 textureDimension;

#define texel_size_x 1.0 / textureDimension[0]
#define texel_size_y 1.0 / textureDimension[1]

vec4 texture2D_bilinear( sampler2D texture, vec2 uv)
{
    vec2 f;
    uv = uv + vec2( - texel_size_x / 2.0, - texel_size_y / 2.0);

    f.x = fract( uv.x * textureDimension[0]);
    f.y = fract( uv.y * textureDimension[1]);

    vec4 t00 = texture2D( texture, vec2(uv));
    vec4 t10 = texture2D( texture, vec2(uv) + vec2( texel_size_x, 0));
    vec4 tA = mix( t00, t10, f.x);

    vec4 t01 = texture2D( texture, vec2(uv) + vec2( 0, texel_size_y));
    vec4 t11 = texture2D( texture, vec2(uv) + vec2( texel_size_x, texel_size_y));
    vec4 tB = mix( t01, t11, f.x);

    vec4 result = mix( tA, tB, f.y);
    return result;
}

Это выглядит довольно просто и прямолинейно. Я недавно протестировал его на нескольких картах ATI (последние версии драйверов...) и получил следующий результат:

Исходные данные (Ближайший соседШейдер в использовании

(Слева: ближайший сосед) (Справа: более жесткий в использовании)

Как вы можете видеть некоторые горизонтальные и вертикальные линии, важно отметить, что они не зафиксированы ни в координатах порта просмотра, ни в координатах текстуры.

Мне пришлось портировать несколько шейдеров, чтобы они работали правильно на картах ATI, кажется, что реализация NVIDIA немного более разрешительна в отношении плохого кода, который я написал некоторое время. Но в этом случае я не вижу, что мне следует изменить!

Что-нибудь общее, что я должен знать о различиях между NVIDIA и ATI GLSL, чтобы преодолеть это?

2 ответа

Решение

Насколько я могу судить, вы не измеряете координату текстуры перед выборкой текстуры. Это может быть причиной появления этих линий, потому что ваша входная координата текстуры лежит именно на границе между текселями. Так что вам нужно квантовать uv сначала в тексель центры. Имейте в виду, что координаты текстуры 0 и 1 находятся не в центрах текселей, а определяют границы сетки, где ячейки сетки - это тексели, а центры текселей - в (texel_n + 0.5) / texture_dimили вы используете функцию GLSL texelFetch доступный GLSL 1.30 и позже.

nVidia более разрешительна, например, nVidia позволяет вам разыгрывать неправильно (т.е. float4 to float), только делая это предупреждение, ATI не будет (ошибка). Существует большая разница, если вы используете OpenGL, чем если вы используете DirectX, например, у меня был довольно сложный вершинный шейдер (скинирование матричной палитры), и даже без малейшего предупреждения он не работал на ATI (но работал на nVidia).

Поэтому, если вы не хотите, чтобы шейдеры работали "везде", приобретите карту ATI:-) (или, что лучше, встроенный чипсет ^^).

Другие вопросы по тегам