OpenGL GLSL以任意形状混合两种纹理

时间:2014-07-09 05:19:31

标签: c++ opengl textures glsl alphablending

我有一个带有两个纹理的全屏四边形。

我想根据用户选择混合任意形状的两个纹理。

例如,四边形首先是100%texture0而texture1是透明的。

如果用户通过在四边形上拖动鼠标来选择一个区域,例如一个圆圈,那么 circle region应该将texture0和texture1都显示为半透明。

未被圆圈包围的区域仍应为texture0。

请参见示例图片,纹理简化为颜色。

image

目前,我已经在四边形上混合了两个纹理,但是混合区域只能是垂直切片,因为我使用了step()函数。

我的碎片着色器:

uniform sampler2D Texture0;
uniform sampler2D Texture1;
uniform float alpha;
uniform float leftBlend;
uniform float rightBlend;
varying vec4 oColor;
varying vec2 oTexCoord;
void main()
{
vec4 first_sample = texture2D(Texture0, oTexCoord);
vec4 second_sample = texture2D(Texture1, oTexCoord);

float stepLeft = step(leftBlend, oTexCoord.x);
float stepRight = step(rightBlend, 1.0 - oTexCoord.x);
if(stepLeft == 1.0 && stepRight == 1.0)
    gl_FragColor = oColor * first_sample;
else
    gl_FragColor = oColor * (first_sample * alpha + second_sample * (1.0-alpha)); 

if (gl_FragColor.a < 0.4)
   discard;
}

为了实现任意形状,我假设我需要创建一个与texture0和texture 1大小相同的alpha蒙版纹理?

然后我将该纹理传递给frag着色器以检查值,如果value为0则为texture0,如果value为1则再混合texture0和texture1。

我的方法是否正确?你能指点我的样品吗?

我希望效果如OpenGL - mask with multiple textures

但我想在我的程序中动态创建蒙版纹理,我想在GLSL中实现混合

我有混合使用黑色和白色的面具纹理

uniform sampler2D TextureMask;
vec4 mask_sample = texture2D(TextureMask, oTexCoord);
if(mask_sample.r == 0)
  gl_FragColor = first_sample;
else
  gl_FragColor =  (first_sample * alpha + second_sample * (1.0-alpha)); 

现在掩码纹理是从磁盘上的图像静态加载的,现在我只需要在opengl中动态创建掩码纹理

1 个答案:

答案 0 :(得分:1)

这是一种方法和样本。

为是否要混合创建布尔测试。 在我的示例中,我使用了一个以屏幕为中心的圆的方程式。

然后混合(我通过加权添加2种颜色混合)。

(注意:我在此示例中没有使用纹理坐标,因此我使用屏幕分辨率来确定圆位置。)

uniform vec2 resolution;

void main( void ) {

    vec2 position = gl_FragCoord.xy / resolution;

    // test if we're "in" or "out" of the blended region
    // lets use a circle of radius 0.5, but you can make this mroe complex and/or pass this value in from the user
    bool isBlended = (position.x - 0.5) * (position.x - 0.5) +
        (position.y - 0.5) * (position.y - 0.5) > 0.25;

    vec4 color1 = vec4(1,0,0,1); // this could come from texture 1
    vec4 color2 = vec4(0,1,0,1); // this could come from texture 2
    vec4 finalColor;

    if (isBlended)
    {
        // blend
        finalColor = color1 * 0.5 + color2 * 0.5;
    }
    else
    {
        // don't blend
        finalColor = color1;
    }
    gl_FragColor = finalColor;
}

请参阅此处运行的示例:http://glsl.heroku.com/e#18231.0

(试图发布我的样本图片,但我没有足够的代表)抱歉:/

更新

这是使用鼠标位置确定混合区域位置的另一个示例。 要运行,请将代码粘贴到此沙箱网站中:https://www.shadertoy.com/new 只要您的鼠标数据设置正确,这个应该可以处理任何形状的对象。

void main(void)
{
vec2 position = gl_FragCoord.xy;

// test if we're "in" or "out" of the blended region
// lets use a circle of radius 10px, but you can make this mroe complex and/or pass this value in from the user
float diffX = position.x - iMouse.x;
float diffY = position.y - iMouse.y;
bool isBlended = (diffX * diffX) + (diffY * diffY) < 100.0;

vec4 color1 = vec4(1,0,0,1); // this could come from texture 1
vec4 color2 = vec4(0,1,0,1); // this could come from texture 2
vec4 finalColor;

if (isBlended)
{
    // blend
    finalColor = color1 * 0.5 + color2 * 0.5;
}
else
{
    // don't blend
    finalColor = color1;
}
gl_FragColor = finalColor;
}