Самый эффективный метод для определения шейдеров GLSL - PullRequest
5 голосов
/ 30 апреля 2011

Я ищу быстрый и грязный, очень эффективный шейдер обнаружения краев или сетку краев для видеоприложения.Так как это будет сделано на мобильном устройстве, мне нужно что-то, что ставит производительность выше точности.В любом случае, я буду размывать вывод, и все алгоритмы обнаружения краев, которые я видел, как правило, делаются путем сравнения с определенным порогом исходного изображения и размытого.Я думаю, что размытие приводит к большинству проблем с производительностью.

У меня есть такая функция:

vec4 edge()
{

    float K00 = -1.0;
    float K01 = -2.0;
    float K02 = -1.0;
    float K10 = 0.0;
    float K11 = 0.0;
    float K12 = 0.0;
    float K20 = 1.0;
    float K21 = 2.0;
    float K22 = 1.0;

    vec2 ox = vec2 (0.0,0.0);
    ox[0] = width;
    vec2 oy = vec2 (0.0,0.0);
    oy[1] = height;

    float g00, g01, g02;
    float g10, g11, g12;
    float g20, g21, g22;
    vec4 CC;

    vec2 PP = TextureCoord - oy;
    CC = texture2D(blurredFrame, vec2(PP-ox));
    g00 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP));
    g01 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP+ox));
    g02 = getGrey(CC);


    PP = TextureCoord;
    CC = texture2D(blurredFrame, vec2(PP-ox));
    g10 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP));
    g11 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP+ox));
    g12 = getGrey(CC);

    PP = TextureCoord + oy;
    CC = texture2D(blurredFrame, vec2(PP-ox));
    g20 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP));
    g21 = getGrey(CC);
    CC = texture2D(blurredFrame, vec2(PP+ox));
    g22 = getGrey(CC);

    float sx = 0.0, sy = 0.0;
    sx = sx + g00 * K00;
    sx = sx + g01 * K01;
    sx = sx + g02 * K02;
    sx = sx + g10 * K10;
    sx = sx + g11 * K11;
    sx = sx + g12 * K12;
    sx = sx + g20 * K20;
    sx = sx + g21 * K21;
    sx = sx + g22 * K22;
    sy = sy + g00 * K00;
    sy = sy + g01 * K10;
    sy = sy + g02 * K20;
    sy = sy + g10 * K01;
    sy = sy + g11 * K11;
    sy = sy + g12 * K21;
    sy = sy + g20 * K02;
    sy = sy + g21 * K12;
    sy = sy + g22 * K22;

    float dist = sqrt(sx * sx + sy * sy);

    return dist > threshold ? vec4 (0,0,0,1) : vec4 (1,1,1,1);
}

Все примеры, которые я видел, похожи на это и, кажется, сосредоточенынастольная платформа - слишком сложная и дорогостоящая, чтобы получить приличную частоту кадров на устройстве iPhone или Android.Это будет только для 2-го приложения, и скорость является ключевой.

Есть идеи, как сделать это более эффективным или, возможно, лучшей альтернативой?Спасибо всем.

Ответы [ 2 ]

4 голосов
/ 01 мая 2011

Не уверен, знаю ли я другой алгоритм.

Но на ум приходят некоторые предложения:

  1. Не используйте sqrt () перед сравнением с dist, сравните с dist ^ 2
  2. Посмотрите, можете ли вы оптимизировать схему доступа для загрузки текстур. Шаблон доступа к текстурной памяти может сильно повлиять на производительность. Вы хотите, чтобы доступ к вашей памяти был как можно более конфиденциальным (т. Е. 0,1,2,3, ...) вместо случайного.
  3. Отключите отображение mip или используйте texture2DLod, где вы вручную указываете уровень карты mip.
1 голос
/ 01 мая 2011

У меня есть пара идей по оптимизации образцов текстур:

  1. Нет необходимости выбирать, где соответствующий коэффициент равен нулю (K1 *).
  2. Использовать texture2DOffsetвместо texture2D.Он принимает постоянные целочисленные смещения, что позволяет драйверу более эффективно прогнозировать ваш шаблон доступа.
  3. Вы взвешиваете выборки.Для этого вы можете использовать встроенную механику линейной фильтрации.Например, чтобы получить сумму выборок в двух соседних текселях, вы можете выполнить линейную (только один раз) выборку между ними и умножить результат на 2. Этот вариант исключает предыдущее предложение.
...