OpenGL GLSL 通过任意形状混合两个纹理
Posted
技术标签:
【中文标题】OpenGL GLSL 通过任意形状混合两个纹理【英文标题】:OpenGL GLSL blend two textures by arbitrary shape 【发布时间】:2014-07-09 05:19:31 【问题描述】:我有一个带有两个纹理的全屏四边形。
我想根据用户选择混合任意形状的两个纹理。
例如,四边形最初是 100% 纹理 0,而纹理 1 是透明的。
如果用户通过在四边形上拖动鼠标来选择一个区域,例如一个圆形,那么 圆形区域应将纹理 0 和纹理 1 显示为半透明。
没有被圆圈包围的区域应该仍然是texture0。
请看示例图片,纹理被简化为颜色。
目前,我已经实现了在四边形上混合两个纹理,但是混合区域只能是垂直切片,因为我使用了 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;
为了实现任意形状,我假设我需要创建一个与纹理 0 和纹理 1 大小相同的 alpha 蒙版纹理?
然后我将该纹理传递给碎片着色器以检查值,如果值为 0,则为纹理 0,如果值为 1,则混合纹理 0 和纹理 1。
我的方法正确吗?你能指出我的任何样本吗?
我想要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】:这是一种方法和示例。
为您是否要混合创建一个布尔测试。 在我的示例中,我使用了一个以屏幕为中心的圆的方程。
然后混合(我通过两种颜色的加权相加混合)。
(注意:我没有在这个示例中使用纹理坐标,所以我使用屏幕分辨率来确定圆的位置)。
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;
【讨论】:
这应该如何适用于任意形状,例如茶壶? 显然简单的圆计算是行不通的。但是布尔测试不是样本的重点。它可以是任何东西,基于着色器的其他输入,例如纹理、纹理坐标等。 谢谢,如果来自 alpha 蒙版纹理,我如何确定 isBlended?我需要有关如何在 opengl 中创建 alpha 蒙版纹理的指针 kevin0228ca:我已经更新了我的答案,以展示如何根据鼠标输入确定混合区域。希望示例站点可以正常工作,这让您了解如何根据更复杂的输入计算混合区域(可能发送单击的框/圆等的左上/右下边界等) kevin0228ca:如果您想为您的 Alpha 蒙版使用纹理,您可以像任何其他纹理一样对其进行采样。基本上,您将从第一个纹理中采样 color1,从第二个纹理中采样 color2,并从第三个纹理中采样掩码值。可以使用帧缓冲区对象或其他方法以编程方式创建纹理。 opengl.org/wiki/Framebuffer_Object以上是关于OpenGL GLSL 通过任意形状混合两个纹理的主要内容,如果未能解决你的问题,请参考以下文章
使用 GLSL 在两个不同的通道上进行 Alpha 混合纹理