2016-05-02 2 views
0

Я хотел бы знать, как создавать собственные фильтры для GPUImage. Сейчас я могу создать сепия пользовательский фильтр из этого кода (это было предусмотрено Brad Larson на GitHub в качестве примера):iOS - Как создать пользовательские GPUImageFilters с OpenGLES

varying highp vec2 textureCoordinate; 

uniform sampler2D inputImageTexture; 

void main() 
{ 
    lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
    lowp vec4 outputColor; 
    outputColor.r = (textureColor.r * 0.393) + (textureColor.g * 0.769) + (textureColor.b * 0.189); 
    outputColor.g = (textureColor.r * 0.349) + (textureColor.g * 0.686) + (textureColor.b * 0.168);  
    outputColor.b = (textureColor.r * 0.272) + (textureColor.g * 0.534) + (textureColor.b * 0.131); 
    outputColor.a = 1.0; 

    gl_FragColor = outputColor; 
} 

Мне интересно знать, как Брэд Ларсон знал эти цифры и что это значит. Я искал везде и не нашел учебника по этому вопросу. Может ли кто-нибудь попросить меня создать мою собственную фотографию для фотографий с помощью Photoshop, а затем перевести ее в файл кода .fsh?

Например, если я хочу изменить изображение в розовый тон в Photoshop. Как получить эти цифры в коде выше?

ответ

2

Ваш вопрос немного широк, поскольку вы можете буквально write an entire book on how to create custom shaders, но это часто заданный вопрос, поэтому я могу по крайней мере указать людям в правильном направлении.

Фильтры в GPUImage написаны на языке затенения OpenGL (GLSL). Есть небольшие различия между целями OpenGL (Mac, настольный Linux) и OpenGL ES (iOS, встроенный Linux), в которых шейдеры на последнем используют прецизионные квалификаторы, отсутствующие в первом. Кроме того, синтаксис один и тот же.

Шейдерные программы состоят из согласованной пары вершинного шейдера и фрагментарного шейдера. Вершинный шейдер работает над каждой вершиной и обычно обрабатывает геометрические манипуляции. Фрагментный шейдер работает над каждым фрагментом (как правило, пикселем) и вычисляет цвет, который будет выводиться на экран в этом фрагменте.

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

Первая строка в главной функции():

lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 

использует функцию texture2D() для чтения цвета пиксела в inputImageTexture при заданной координате (передаются из вершинного шейдера на первом этапе). Эти координаты нормируются на диапазон 0.0-1.0 и поэтому не зависят от размера входного изображения.

Значения загружаются в векторный тип (vec4), который содержит несколько компонентов в одном типе. В этом случае цветовые компоненты для красного, зеленого, синего и альфа хранятся в этом четырехкомпонентном векторе и могут быть доступны через .r, .g, .b и .a. Значения компонентов цвета также нормализуются до диапазона 0.0-1.0, если вы привыкли работать со значениями 0-255.

В конкретном случае фильтра тонов сепии я пытаюсь применить a well-known color matrix для эффекта тона сепии для преобразования входящего цвета в исходящий. Это требует матричного умножения, которое я делаю явно в коде выше. В реальной структуре это делается как матричная математика с использованием встроенных типов в шейдере.

Существует множество способов манипулирования цветами для достижения определенных эффектов. Структура GPUImage полна их, основанная в основном на таких вещах, как стандарты преобразования цвета, опубликованные Adobe или другими организациями. Для данного эффекта вы должны определить, будет ли одна из этих существующих реализаций делать то, что вы хотите, прежде чем указывать свою собственную.

Если вы хотите написать свое собственное, сначала вычислите математику, необходимую для перевода входящих цветов в любой выходной сигнал, который вы хотите. Как только вы это сделаете, писать шейдерный код легко.

Фильтр поиска в GPUImage использует другой подход, и это должно начаться с изображения, которое вы управляете в Photoshop, в условиях фильтра, которые вы хотите имитировать. Затем вы берете это фильтрованное изображение и присоединяете его к фильтру поиска. Он переводит между входящими цветами и их эквивалентами в поиске для обеспечения произвольной цветовой манипуляции.

Как только у вас есть шейдер, вы можете создать новый фильтр вокруг этого несколькими способами. Я должен сказать, что мой новый GPUImage 2 framework значительно упрощает этот процесс, если вы готовы отказаться от обратной совместимости.