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

Еще одна проблема состоит в том, что язык шейдеров OpenGL хотя и поддерживает циклы, даже вложенные, но не поддерживает двухмерные массивы. В принципе можно «раскрутить» ядро свёртки и хранить его в одномерном массиве, в каждой ячейке которого будут храниться х- и г/-координаты (сдвиг) от центра ядра и значение в этой точке. Во фрагментном шейдере можно обработать весь массив в одном цикле, прибавляя указанный сдвиг к текущим текстурным координатам, обращаясь к основному изображению и умножая полученное значение пиксела на значение из ядра. Если ядро свёртки будет храниться в таком виде, значения можно записывать в массив как угодно: по строкам, по столбцам, в обратном порядке или вообще в произвольном порядке. В массив даже не нужно включать нулевые значения ядра, так как они никак не влияют на результат.

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

Шейдеры для обработки изображения

В случае если ядро свёртки выходит за край основного изображения, требуется особое решение. Можно использовать один из побочных эффектов текстурных операций OpenGL: если приложение хочет нарисовать край так, чтобы получился результат в режиме GL_CONSTANT_BORDER, текстура с основным изображением должна содержать в GL_TEXTURE_WRAP_S и GL_TEXTURE_WRAP_T параметр GL_CLAMP_TO_BORDER. Если же нужен край вида GL_RЕРLI CATE_B0RDER (при выходе ядра за край берется крайний пиксел изображения), то параметры текстуры GL_TEXTURE_WRAP_S и GL_TEXTURE_WRAP_T должны быть установлены в GL_CLAMP_TO_EDGE. А если нужен режим GL_REDUCE, приложение должно рисовать прямоугольник, немного меньший свертываемого изображения. Для размера ядра 3x3 прямоугольник должен быть меньше на 2 пиксела в ширину и на 2 пиксела в высоту. В этом случае текстурная координата нижнего левого угла будет (1/width, 1/height), а текстурная координата верхнего правого угла -(1 - 1/width, 1 - 1/height). Режим текстуры нужно установить в GL_NEAREST, чтобы избежать ненужной интерполяции.


⇐ Предыдущая| |Следующая ⇒