我有一个 OpenGL ES Shader 片段着色器,它使用混合函数在视频帧上放置一个叠加层。这是我的着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 textureCoordinate;
uniform sampler2D videoFrameY;
uniform sampler2D videoFrameUV;
uniform sampler2D overlay;
const mat3 yuv2rgb = mat3(
1, 1, 1,
0, -.21482, 2.12798,
1.28033, -.38059, 0
);
void main() {
vec3 yuv;
vec4 ovr;
yuv.x = texture2D(videoFrameY, textureCoordinate).r;
yuv.yz = texture2D(videoFrameUV, textureCoordinate).rg - vec2(0.5, 0.5);
ovr = texture2D(overlay, textureCoordinate);
vec3 rgb = yuv2rgb * yuv;
gl_FragColor = mix(ovr, vec4(rgb, 1.0), ovr.a);
}
没有覆盖纹理,提供 gl_FragColor
这个:
gl_FragColor = vec4(rgb, 1.0);
工作正常,我的视频显示出来了。现在我从 CATextLayer
创建我的覆盖纹理,如下所示:
- (void)generateOverlay {
CATextLayer *textLayer = [CATextLayer layer];
[textLayer setString:@"Sample test string"];
[textLayer setFont:(__bridge CFStringRef)@"Helvetica"];
[textLayer setFontSize:(_videoHeight / 6)];
[textLayer setAlignmentMode:kCAAlignmentLeft];
[textLayer setBounds:CGRectMake(0, 0, _videoWidth, _videoHeight)];
CGSize layerSize = textLayer.bounds.size;
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc(layerSize.height * layerSize.width * 4);
CGContextRef context = CGBitmapContextCreate(imageData, layerSize.width, layerSize.height, 8, 4 * layerSize.width, colorspace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorspace);
CGContextClearRect(context, CGRectMake(0, 0, layerSize.width, layerSize.height));
CGContextTranslateCTM(context, 0, layerSize.height - layerSize.height);
[textLayer renderInContext:context];
glActiveTexture(GL_TEXTURE2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layerSize.width, layerSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
}
问题是结果是颠倒的。因此,它们看起来像这样:
(来源:c.tro.pe)
事实上,它们在两个方面是颠倒的。首先,不是蓝色被 alpha 输出和视频显示,文本是 alpha,这就是视频显示的地方。第二,文字是镜像的。镜像可能是使用顶点值的结果,但是使用相同坐标的视频是正确的。我确定这是一个快速的重新排列,但我不确定要调整什么。谢谢!
最佳答案
对于混合,mix(x, y, a)
函数根据a< 在
。 0 的 x
和y
之间进行插值a
给你所有的 x
,而 1.0 的 a
给你所有的 y
。您正在关闭文本层的 alpha,因此对于您想要的叠加层,您需要按如下方式反转顺序:
gl_FragColor = mix(vec4(rgb, 1.0), ovr, ovr.a);
关于旋转,请记住 iOS 后置摄像头横向安装在左侧,前置摄像头横向安装在右侧,因此对于纵向方向,您需要旋转传入的视频帧。您似乎在顶点或纹理坐标中执行该旋转。您将需要第二组未旋转的纹理坐标以用于对叠加图像进行采样,或者您需要在生成其纹理时以匹配的横向左旋转绘制标签。
关于iphone - 在 iOS 上的 OpenGL ES 着色器中混合多个纹理会导致相反的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10908710/