如何更新纹理的某个通道

时间:2020-06-12 08:00:08

标签: opengl

我现在正在使用FFMPEG读取高分辨率视频(6480 * 1920)并使用opengl进行显示

解码后,我得到3个指向Y,U,V的指针。

首先,我使用swsscale将其转换为rgb并显示它,但是我发现它太慢了。所以我直接与YUV打交道。我的第二个尝试是生成3个单通道纹理,然后在片段着色器中将其转换为rgb。它速度更快,但仍无法达到60fps

我发现此功能的瓶颈是:texture(texy,tex_coord.xy)。当纹理很大时,会花费很多时间。因此,而不是将其称为3次,我的想法是将YUV放在一个单一的纹理中,因为一个纹理可以具有4个通道。但我想知道如何更新纹理的某个通道。

我尝试了以下代码,但似乎不起作用。 glTexSubImage2D不会更改通道,而是会更改整个纹理:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, frame->width, frame->height,0, GL_RED, GL_UNSIGNED_BYTE, Y);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,frame->width, frame->height, GL_GREEN,U);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,frame->width, frame->height, GL_BLUE,V);

那么,如何使用一种纹理传递YUV数据?我还尝试将YUV数据收集到一个数组中,然后生成纹理。但这无济于事,因为它需要大量时间来生成该数组。

有什么好主意吗?

1 个答案:

答案 0 :(得分:1)

您正从错误的角度来解决这个问题,因为您一开始实际上并不了解是什么原因导致性能不佳。是的,纹理访问是一项相当昂贵的操作。但这并不昂贵。我的意思是,只需考虑一下在现代游戏中以很高的帧速率传输的纹理数据量。

问题不是纹理的通道格式,也不是GLSL texture的调用。

您的问题是这个

(…)高分辨率视频(6480 * 1920)

简单而简单的框架尺寸超出了GPU可以使用的范围。尝试将图片分解为一组较小的纹理。使用glPixelStorei参数GL_UNPACK_ROW_LENGTHGL_UNPACK_SKIP_PIXELSGL_UNPACK_SKIP_ROWS,您可以选择要复制的源图片内部的矩形。

您不必进行多次绘制调用,只需根据目标片段位置或纹理坐标选择着色器内的纹理即可。

不幸的是,OpenGL并没有提供确定甜蜜点的便捷功能,对于当今的大多数GPU,密集纹理的任一方向的最大大小为2048。超过它,以我的经验,密集纹理的性能就很低。 / p>

稀疏纹理是一本完全不同的章节,与该问题无关。

仅出于完整性考虑:我认为,您不必通过调用glTexImage2D来重新初始化每一帧的纹理。在视频开始时只执行一次,然后只需更新纹理即可。

相关问题