2012-01-25 3 views
6

Я работаю над 2D-iOS-игрой, используя OpenGL 2.0, и мне интересно, можно ли написать шейдер, который будет отображать изображения с сиянием. Все изображения являются двумерными спрайтами. Примеры шейдеров, которые я видел для выделения, предназначены для трехмерных объектов, поэтому я не уверен, что это возможно для 2D-изображений.OpenGL ES Shader для выделения 2D-изображений

+0

так что свечение, которое вы хотите добавить, похоже на тень? –

+0

Больше обводки вокруг изображения, которое будет иметь мягкие края. –

ответ

7

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

На практике вы, вероятно, могли бы просто повторно использовать триггерные шейдеры, которые вы видели - хотя теоретически можно было бы проверить количество глубин (с некоторыми расширенными усилиями в ES), каждый из тех, что я когда-либо видел, был всего лишь 2d-эффектом на отображаемое изображение.

EDIT: при дальнейшем рассмотрении лапласиан может быть немного легче применен, чем Sobel, поскольку он может быть выполнен как простые сверточные шейдеры (как описано в местах like this). Хотя, чтобы быть в безопасности на мобильном телефоне, вы, возможно, захотите больше придерживаться ядер 3x3 и писать разные шейдеры для каждого эффекта, а не делать это с данными. Так, например, грубый Гауссово размывание, выписана в длину:

void main() 
{ 
    mediump vec4 total = vec4(0.0); 
    mediump vec4 grabPixel; 

    total +=  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, -1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(1.0/width, -1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(1.0/width, 1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, 1.0/height)); 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(0.0, -1.0/height)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(0.0, 1.0/height)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, 0.0)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(1.0/width, 0.0)); 
    total += grabPixel * 2.0; 

    grabPixel = texture2D(tex2D, texCoordVarying); 
    total += grabPixel * 4.0; 

    total *= 1.0/16.0; 

    gl_FragColor = total; 
} 

И лапласиане край обнаружения заканчивает тем, что аналогичные, но с различными константами.

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

+0

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

+0

Многие ячеистые шейдеры пост-струйной установки используют положение камеры для обнаружения краев, определяя край, чтобы быть соединением между передним лицом к краю и обратным обратным краем. Очевидно, вы не сможете использовать один из них. Но такие подходы, как Собель и Лапласиан, ищут разрывы в цвете в двухмерном изображении, чтобы пятно краев, так что вполне уместны. Вероятно, полезно читать на фильтрах свертки, если вы еще этого не сделали, тогда исследуйте лапласианское и гауссовское размытие. Я добавил несколько поспешно собранных примеров кода для последнего. – Tommy

Смежные вопросы