如何加快 OpenGL 中纹理的绘制速度? (3.3+/4.1)

Posted

技术标签:

【中文标题】如何加快 OpenGL 中纹理的绘制速度? (3.3+/4.1)【英文标题】:How can I speed up painting on a texture in OpenGL? (3.3+/4.1) 【发布时间】:2014-10-06 16:45:17 【问题描述】:

我正在用鼠标在 3D 对象上绘图。

我现在的做法是通过片段着色器将 UV 坐标打包到 RG 像素,如下所示:

in highp vec2 UV;
out vec4 fragColor;
void main()

    fragColor.r = UV.x;
    fragColor.g = UV.y;

我将它们渲染到屏幕外 FBO,然后在鼠标下读取像素以获取 CPU 端的 UV 坐标。

float pixel_array[4];

CALL_GL(glReadBuffer(GL_COLOR_ATTACHMENT0));
CALL_GL(glReadPixels(normMouseX*WINDOW_WIDTH,normMouseY*WINDOW_HEIGHT,1,1,GL_RGBA,GL_FLOAT,pixel_array));

float u = pixel_array[0];
float v = pixel_array[1];

然后我使用这些 UV 坐标在正确的位置“绘制”纹理。

CALL_GL(glBindTexture(GL_TEXTURE_2D, mesh.diffuseTexture));
CALL_GL(glTexSubImage2D(GL_TEXTURE_2D,
        0,
        u*diffuseTextureWidth,
        v*diffuseTextureHeight,
        5,
        5,
        GL_RGBA,
        GL_UNSIGNED_BYTE,
        brush_pixels));

问题在于,根据纹理的分辨率,这个过程非常缓慢。有什么方法可以加快速度吗?

【问题讨论】:

【参考方案1】:

我将它们渲染到屏幕外 FBO,然后在鼠标下读取像素以获取 CPU 端的 UV 坐标。

确保仅在真正需要时从该纹理进行回读。也尝试突发读回。读取单个像素,这通常是低效的。每次更新(改变视图后)读取整个纹理是有效的。

要加速绘制到纹理而不是 glTexSubImage2D-ing 它,只需将其绑定到 FBO 作为颜色附件并使用常规 OpenGL 绘制操作绘制到它。

【讨论】:

嗯,我一直认为从 GPU 端读取任何内容都很慢。不过,您的回答比我的要好得多,甚至没有想过使用 OpenGL 操作来绘制(哦,具有讽刺意味)。 @BWG: 以前GPU和CPU之间的连接是通过AGP的非对称带宽连接的。今天我们得到了对称带宽大于 10GiB/s 的 PCI-E 3。使用 PBO 和良好对齐的访问并为读出缓冲区选择本机像素格式和布局,GPU 可以执行异步 DMA 传输。但从技术上讲,您可以在 Shader Model 3 GPU 上执行所有操作,包括将画笔放置在目标纹理上。在顶点着色器中,您可以从几何缓冲区纹理中读取并根据读取的 UV 坐标扭曲放置“画笔”网格,然后绘制它。 @Jubei:不,我的意思是像素缓冲区对象。 PBO 是 OpenGL 中的一种代理对象,允许您在 GPU 和系统内存之间异步传输像素数据,而无需通过 CPU 同步事件强制 GPU 停止流水线。本质上,您可以通过调用 glReadPixels 立即将 glReadPixels 放入 PBO 中。然后,您可以向 GPU 发出更多命令,这些命令可以与向 PBO 的复制操作并行执行。稍后您可以从 PBO 获取数据,然后才可能需要 GPU 进行同步。 @Jubei:PBO 的想法是推迟 GPU-CPU 同步,在这种同步干扰较小甚至可能根本不会造成干扰的时间点。 @Jubei:是的,glReadPixels 是一个相对昂贵的操作。但请记住,您必须仅在视图更改时才传输 UV 几何缓冲区图像。只要视图保持不变就可以重复使用相同的回读 UV 数据;您不必每次鼠标笔划都为每个 glReadPixels 设置。

以上是关于如何加快 OpenGL 中纹理的绘制速度? (3.3+/4.1)的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL之Mipmap、压缩纹理

绘制opengl纹理的一部分

OpenGL VBO 不显示

如何在OpenGL中将像素作为纹理绘制到多边形?

我的OpenGL学习进阶之旅解决OpenGL绘制带透明通道的png纹理时出现黑边问题,并彻底了解其原理

用OpenGL绘制多纹理?