2013-08-31 3 views
8

Я изучаю OpenGL ES 2.0, и я хотел бы создать приложение, чтобы лучше понять, как он работает. Приложение имеет набор фильтров, которые пользователь может применять на изображениях (я знаю, ничего нового: P).Изображения и маска в OpenGL ES 2.0

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

enter image description here

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

У вас есть подсказка, чтобы помочь мне в этом проекте?

EDIT --------

Я нашел решение, но когда я использую в качестве маски линий вместо кругов результат действительно «шероховатый», особенно если линии вращаются.

precision highp float; 

varying vec4 FragColor; 
varying highp vec2 TexCoordOut; 

uniform sampler2D textureA; 
uniform sampler2D textureB; 
uniform sampler2D mask; 

void main(void){ 
    vec4 mask_color = texture2D(mask, TexCoordOut); 

    if (mask_color.a > 0.0){ 
     gl_FragColor = texture2D(textureA, TexCoordOut); 
    }else { 
     gl_FragColor = texture2D(textureB, TexCoordOut); 
    } 
} 

Возможно ли, вероятно, использовать буфер или смешивание трафарета?

+3

Кстати, вам не нужно использовать канал alpha ('mask_color.a') для маски. Вы можете использовать любой другой канал 'r',' g', 'b', и таким образом вы сэкономите память GPU, используя текстуру маски без альфа-канала. – keaukraine

+0

@MatterGoal Может быть, вы можете ответить на этот вопрос, http://stackoverflow.com/questions/24486729/uiimage-masking-with-gesture –

ответ

12

Вы можете применить маску в одной строке без использования дорогостоящих if:

gl_FragColor = step(0.5, vMask.r) * vColor_1 + (1.0 - step(0.5, vMask.r)) * vColor_2; 

Или лучше просто интерполировать между двумя цветами:

gl_FragColor = mix(vColor_1, vColor_2, vMask.r); 

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

+0

Можно ли использовать multipass для создания размытой маски? Или вы предлагаете создать размытие с тем же шейдером? – MatterGoal

+2

Вы можете создать размытие с тем же шейдером, выполнив несколько (например, 5) замаскиваний маски и усредняя результат. Затем используйте это среднее значение вместо '' vMask.r''. –

+2

Здесь вы можете найти реализацию gaussing blur в фрагмент-шейдере: http://xissburg.com/faster-gaussian-blur-in-glsl/ –

1

Нет необходимости в использовании нескольких шейдеров или фреймбуферов, всего несколько блоков текстуры. Просто используйте 3 текстурных блока, которые все индексируются по одинаковым координатам текстуры и используют текстуру Маски для выбора между двумя другими текстурами. Пиксельный шейдер будет выглядеть следующим образом:

uniform sampler2D uTextureUnit_1; 
uniform sampler2D uTextureUnit_2; 
uniform sampler2D uTextureMask; 
varying vec2 vTextureCoordinates; 

void main() 
{ 
    vec4 vColor_1 = texture2D(uTextureUnit_1, vTextureCoordinates); 
    vec4 vColor_2 = texture2D(uTextureUnit_2, vTextureCoordinates); 
    vec4 vMask = texture2D(uTextureMask, vTextureCoordinates); 

    if (vMask.r > 0.5) 
     gl_FragColor = vColor_1; 
    else 
     gl_FragColor = vColor_2; 
} 

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

+0

Вы предлагаете применить какие-либо конкретные настройки к сцене, чтобы получить идеальный результат? Для некоторых «нелинейных» масок я получаю ужасный конечный результат. – MatterGoal

+2

OpenGL специально не обеспечивает идеальные результаты, но вы можете улучшить качество, увеличив размеры текстур. Для glTexParameteri() используйте GL_LINEAR для MAG_FILTER и MIN_FILTER. MIP_MAP помогает только при уменьшении. – ClayMontgomery