Ios OpenGL/GLSE alpha掩蔽

Ios OpenGL/GLSE alpha掩蔽,ios,opengl-es,glsl,Ios,Opengl Es,Glsl,我正在使用OpenGL/GLSL实现一个绘画应用程序。 有一个功能,用户通过使用带有图案图像的画笔绘制“遮罩”,同时背景根据画笔的位置而变化。观看视频,了解: 我用CALayer的面具(iOS的东西)来达到这个效果(在视频中)。但是这种实现非常昂贵,fps非常低。所以我决定用OpenGL来实现。 对于OpenGL实现,我使用模具缓冲区进行掩蔽,即: glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0); glStencilOp(GL

我正在使用OpenGL/GLSL实现一个绘画应用程序。 有一个功能,用户通过使用带有图案图像的画笔绘制“遮罩”,同时背景根据画笔的位置而变化。观看视频,了解:

我用CALayer的面具(iOS的东西)来达到这个效果(在视频中)。但是这种实现非常昂贵,fps非常低。所以我决定用OpenGL来实现。 对于OpenGL实现,我使用模具缓冲区进行掩蔽,即:

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Draw mask (brush pattern)
glStencilFunc(GL_EQUAL, 1, 255);
// Draw gradient background
// Display the buffer
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
问题是:模具缓冲区不适用于alpha,这就是为什么我不能为笔刷使用半透明图案。
问题是:如何通过使用OpenGL/GLSL而不使用模具缓冲区来实现视频效果?

模具是一个布尔开/关测试,因此正如您所说,它无法处理alpha

使用alpha的唯一GL技术是混合,但是由于帧之间的颜色变化,您不能在一次过程中将其简单地展平到单个层中


在我看来,这听起来像是你们需要在屏幕外的缓冲区中保持多个独立的层,然后每帧将它们混合在一起,形成屏幕上显示的内容。这使您能够完全独立于每帧更新每个层的方式。

模具是一个布尔开/关测试,所以正如您所说,它无法处理alpha

使用alpha的唯一GL技术是混合,但是由于帧之间的颜色变化,您不能在一次过程中将其简单地展平到单个层中


在我看来,这听起来像是你们需要在屏幕外的缓冲区中保持多个独立的层,然后每帧将它们混合在一起,形成屏幕上显示的内容。这使您可以完全独立于每帧更新每个层的方式。

由于您的背景已经生成(来自注释),因此您只需在着色器中使用2个纹理来绘制每个片段。您将需要重新绘制所有这些内容,直到用户抬起手指为止

因此,假设您有一个带有alpha通道
footprintTextureID
和背景纹理“backgroundTextureID”的白色足迹纹理。您需要使用
activeTexture
1和2绑定两个纹理,并将2作为一致性传递到着色器中

现在,在顶点着色器中,需要从该位置生成相对纹理坐标。应该有一行类似于
gl\u Position=computedPosition因此,您需要添加另一个
变化的
值:

backgroundTextureCoordinates = vec2((computedPosition.x+1.0)*0.5, (computedPosition.y+1.0)*0.5);
或者如果你需要垂直翻转

backgroundTextureCoordinates = vec2((computedPosition.x+1.0)*0.5, (-computedPosition.y+1.0)*0.5):
(此等式的原因是输出顶点位于间隔
[-1,1]
中,但纹理使用
[0,1]
[-1,1]+1=[0,2]
然后
[0,2]*0.5=[0,1]

好的,假设您正确绑定了所有这些,现在只需将片段着色器中的颜色相乘即可获得混合颜色:

uniform sampler2D footprintTexture;
varying lowp vec2 footprintTextureCoordinate;

uniform sampler2D backgroundTexture;
varying lowp vec2 backgroundTextureCoordinates;

void main() {
    lowp vec4 footprintColor = texture2D(footprintTexture, footprintTextureCoordinate);
    lowp vec4 backgroundColor = texture2D(backgroundTexture, backgroundTextureCoordinates);
    gl_FragColor = footprintColor*backgroundColor;
}

如果您愿意,您可以从封装外形中乘以alpha值,但这只会失去灵活性。在footprint纹理变为白色之前,它不会有任何区别,因此这是您的选择。

由于您的背景已经生成(来自注释),因此您只需在着色器中使用2个纹理来绘制每个分段。您将需要重新绘制所有这些内容,直到用户抬起手指为止

因此,假设您有一个带有alpha通道
footprintTextureID
和背景纹理“backgroundTextureID”的白色足迹纹理。您需要使用
activeTexture
1和2绑定两个纹理,并将2作为一致性传递到着色器中

现在,在顶点着色器中,需要从该位置生成相对纹理坐标。应该有一行类似于
gl\u Position=computedPosition因此,您需要添加另一个
变化的
值:

backgroundTextureCoordinates = vec2((computedPosition.x+1.0)*0.5, (computedPosition.y+1.0)*0.5);
或者如果你需要垂直翻转

backgroundTextureCoordinates = vec2((computedPosition.x+1.0)*0.5, (-computedPosition.y+1.0)*0.5):
(此等式的原因是输出顶点位于间隔
[-1,1]
中,但纹理使用
[0,1]
[-1,1]+1=[0,2]
然后
[0,2]*0.5=[0,1]

好的,假设您正确绑定了所有这些,现在只需将片段着色器中的颜色相乘即可获得混合颜色:

uniform sampler2D footprintTexture;
varying lowp vec2 footprintTextureCoordinate;

uniform sampler2D backgroundTexture;
varying lowp vec2 backgroundTextureCoordinates;

void main() {
    lowp vec4 footprintColor = texture2D(footprintTexture, footprintTextureCoordinate);
    lowp vec4 backgroundColor = texture2D(backgroundTexture, backgroundTextureCoordinates);
    gl_FragColor = footprintColor*backgroundColor;
}

如果您愿意,您可以从封装外形中乘以alpha值,但这只会失去灵活性。在足迹纹理变为白色之前,它不会有任何区别,因此这是您的选择。

您说背景会发生变化。那么你已经有了一个合适的背景了?如果是,背景是否定义为全屏纹理?@MaticOblak,是的,我为每次绘制迭代生成了一个合适的背景。我使用着色器生成渐变,作为输入数据,我使用触摸坐标(“开始”和“结束”触摸)。那么你已经有了一个合适的背景了?如果是,背景是否定义为全屏纹理?@MaticOblak,是的,我为每次绘制迭代生成了一个合适的背景。我使用着色器生成渐变,作为输入数据,我使用触摸坐标(“开始”和“结束”触摸)。这是我一直在思考的问题。实际上,您可以创建一个FBO,该FBO将使用颜色遮罩来禁用alpha来绘制背景色,然后仅使用alpha通道绘制图像。但我想说,这里的问题是,当一条路穿过它自己时会发生什么?我希望如果你创建一个圆,那么第一个(底部)图像将是红色的,而与第一个重叠的最后一个(顶部)图像将是绿色的。但这与使用背景方法相冲突…即使这样做,也更容易仅使用背景纹理(拖动时会发生变化),然后使用具有2个纹理(足迹图像和背景图像)的着色器,然后操纵纹理