Iphone 在iOS上的OpenGL ES着色器中混合多个纹理会导致相反的行为

Iphone 在iOS上的OpenGL ES着色器中混合多个纹理会导致相反的行为,iphone,objective-c,ios,ipad,opengl-es,Iphone,Objective C,Ios,Ipad,Opengl Es,我有一个OpenGL ES着色器片段着色器,它使用mix函数在视频帧上放置覆盖。这是我的着色器: #ifdef GL_ES precision mediump float; #endif varying vec2 textureCoordinate; uniform sampler2D videoFrameY; uniform sampler2D videoFrameUV; uniform sampler2D overlay; const mat3 yuv2rgb = mat3(

我有一个OpenGL ES着色器片段着色器,它使用mix函数在视频帧上放置覆盖。这是我的着色器:

#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 = 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);

}
问题是结果是相反的。因此它们看起来像这样:

- (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);

}

(来源:)

事实上,它们在两个方面是相反的。首先,文本不是蓝色的字母,而是视频显示的字母,这就是视频显示的地方。其次,文本是镜像的。镜像可能是使用顶点值的结果,但是使用相同坐标系时视频是正确的。我相信这是一个快速的重新安排,但我不知道该调整什么。谢谢

对于混合,基于
a
mix(x,y,a)
函数在
x
y
之间插值
a
为0表示所有
x
,而
a
为1.0表示所有
y
。您正在为文本层的alpha设置关键帧,因此对于所需的覆盖,您需要按如下方式反转顺序:

gl_FragColor = mix(vec4(rgb, 1.0), ovr, ovr.a);
关于旋转,请记住,iOS后摄像头安装在横向左侧,前摄像头安装在横向右侧,因此对于纵向方向,您需要旋转传入的视频帧。您似乎正在顶点或纹理坐标中执行该旋转。您将需要第二组不旋转的纹理坐标来对覆盖图像进行采样,或者在生成其纹理时,您需要以匹配的横向左旋转绘制标签。

对于混合,使用
混合(x,y,a)
函数基于
a
x
y
之间插值
a
为0表示所有
x
,而
a
为1.0表示所有
y
。您正在为文本层的alpha设置关键帧,因此对于所需的覆盖,您需要按如下方式反转顺序:

gl_FragColor = mix(vec4(rgb, 1.0), ovr, ovr.a);

关于旋转,请记住,iOS后摄像头安装在横向左侧,前摄像头安装在横向右侧,因此对于纵向方向,您需要旋转传入的视频帧。您似乎正在顶点或纹理坐标中执行该旋转。您将需要第二组纹理坐标,这些坐标不会旋转以用于对覆盖图像进行采样,或者您需要在生成纹理时以匹配的横向左旋转绘制标签。

gl\u FragColor中的更改非常有效。一年过去了,我完全忘记了顶点和位置坐标是如何工作的。我知道我的四元组的位置是(-1,-1)(1,-1)(-1,1)和(1,1)。暂时忘记了文本层,对于横向正确的设备方向,我在s和d纹理坐标方面遇到了问题。它们是按什么顺序绘制的,这样我就不会得到镜像图像?对于(1,0)(0,0)(1,1)(0,1)的tex坐标,我最终得到一个在X和Y上都镜像的图像。我将使用仿射变换来担心文本层。一切都好。我读了这个。我只是把它画在纸上,然后把科技图反方向画出来。现在我有了(0,1)(1,1)(0,0)(1,0),视频在X和Y两个方向都是正确的。至于文本,我将翻转上下文。
gl_FragColor
中的更改非常有效。一年过去了,我完全忘记了顶点和位置坐标是如何工作的。我知道我的四元组的位置是(-1,-1)(1,-1)(-1,1)和(1,1)。暂时忘记了文本层,对于横向正确的设备方向,我在s和d纹理坐标方面遇到了问题。它们是按什么顺序绘制的,这样我就不会得到镜像图像?对于(1,0)(0,0)(1,1)(0,1)的tex坐标,我最终得到一个在X和Y上都镜像的图像。我将使用仿射变换来担心文本层。一切都好。我读了这个。我只是把它画在纸上,然后把科技图反方向画出来。现在我有了(0,1)(1,1)(0,0)(1,0),视频在X和Y中都是正确的。至于文本,我将翻转上下文。