Opengl 如何更新纹理的特定通道

Opengl 如何更新纹理的特定通道,opengl,Opengl,我现在使用FFMPEG读取高分辨率视频(6480*1920)并使用opengl显示它 解码后,我得到了指向Y,U,V的3个指针 起初,我使用swsscale将其转换为rgb并显示,但我发现它太慢了。所以我直接和你打交道。我的第二个尝试是生成3个单通道纹理,并在片段着色器中将其转换为rgb。速度更快,但仍无法达到60帧/秒 我发现瓶颈是这个函数:纹理(texy,tex_-coord.xy)。当纹理较大时,需要花费大量时间。因此,我的想法是将YUV放在一个纹理中,而不是三次调用,因为一个纹理可以有4

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

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

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

我发现瓶颈是这个函数:纹理(texy,tex_-coord.xy)。当纹理较大时,需要花费大量时间。因此,我的想法是将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数据收集到一个数组中,然后生成纹理。但是它没有帮助,因为它需要很多时间来生成该数组


有什么好主意吗?

你从一个错误的角度来看待这个问题,因为你根本不知道是什么原因导致了糟糕的性能。是的,纹理访问是一项相当昂贵的操作。但它并没有那么贵;我的意思是,想想现代游戏中以极高帧速率传输的大量纹理数据

问题不在于纹理的通道格式,也不在于GLSL
纹理的调用

你的问题是:

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

简单明了的框架尺寸超出了GPU使用的舒适范围。尝试将图片分解为一组较小的纹理。使用
glPixelStorei
参数
GL_UNPACK_ROW_LENGTH
GL_UNPACK_SKIP_PIXELS
GL_UNPACK_SKIP_ROWS
可以选择源图片内的矩形进行复制

顺便说一句,您不必进行多次绘制调用,只需基于目标片段位置或纹理坐标选择着色器内部的纹理即可

不幸的是,OpenGL并没有提供一个方便的函数来确定最佳点,对于现在的大多数GPU来说,密集纹理在两个方向上的最大大小都是2048。在我的经验中,在它之上是密集纹理的性能坦克

稀疏纹理是一个完全不同的章节,与这个问题无关


为了完整起见:我认为您不需要调用
glTexImage2D
来重新初始化每个帧的纹理。仅在视频开始时执行一次,然后更新纹理即可。

谢谢您的建议。我将尝试将图像分解为一半大小,以查看性能。