OpenGL OpenGL ES 帧缓冲区位块传送(Blit)

简介: 上文 OpenGL ES 多目标渲染(MRT) 中我们了解了利用 MRT 技术可以一次渲染到多个缓冲区,本文将利用帧缓冲区位块传送实现高性能缓冲区之间的像素拷贝。

作者:字节流动

来源:https://blog.csdn.net/Kennethdroid/article/details/109032497


OpenGL ES 帧缓冲区位块传送

帧缓冲区位块传送(Blit)也是 OpenGL ES 3.0 的新特性,主要用于帧缓冲区之间的像素拷贝,性能高且使用方便,可以指定缓冲区任意矩形区域的像素拷贝。

image.png

本文的绘制流程是,新建一个 FBO 绑定纹理作为颜色附着,然后绑定该帧缓冲区进行一次离屏渲染,最后绑定渲染到屏幕的缓冲区作为渲染缓冲区,从新的帧缓冲区中拷贝像素。

渲染代码:

//首先获取当前默认帧缓冲区的 id 
GLint defaultFrameBuffer = GL_NONE;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFrameBuffer);
//绑定我们新创建的帧缓冲区进行渲染
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
glViewport ( 0, 0, m_RenderImage.width, m_RenderImage.height);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffers(ATTACHMENT_NUM, attachments);
glUseProgram (m_ProgramObj);
glBindVertexArray(m_VaoId);
UpdateMVPMatrix(m_MVPMatrix, 0, m_AngleY, (float)screenW / screenH);
glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_TextureId);
glUniform1i(m_SamplerLoc, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);
//绑定默认的帧缓冲区对象,将像素从新建的帧缓冲区拷贝到当前默认的帧缓冲区
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFrameBuffer);
glViewport ( 0, 0, m_SurfaceWidth, m_SurfaceHeight);
glClear(GL_COLOR_BUFFER_BIT);
//位块传送
BlitTextures();

进行帧缓冲区间位块传之前,需要指定好源帧缓冲区 GL_READ_FRAMEBUFFER 和目标帧缓冲区 GL_DRAW_FRAMEBUFFER,下面代码实现是将四个颜色附着对应的缓冲区像素,分别拷贝到当前渲染缓冲区中的 1/4 矩形区域内:

void FBOBlitSample::BlitTextures() {
  //很重要,指定源帧缓冲区
  glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
  glReadBuffer(GL_COLOR_ATTACHMENT0);
  glBlitFramebuffer(0, 0, m_RenderImage.width, m_RenderImage.height,
            0, 0, m_SurfaceWidth/2, m_SurfaceHeight/2,
            GL_COLOR_BUFFER_BIT, GL_LINEAR);
  glReadBuffer(GL_COLOR_ATTACHMENT1);
  glBlitFramebuffer(0, 0, m_RenderImage.width, m_RenderImage.height,
            m_SurfaceWidth/2, 0, m_SurfaceWidth, m_SurfaceHeight/2,
            GL_COLOR_BUFFER_BIT, GL_LINEAR);
  glReadBuffer(GL_COLOR_ATTACHMENT2);
  glBlitFramebuffer(0, 0, m_RenderImage.width, m_RenderImage.height,
            0, m_SurfaceHeight/2, m_SurfaceWidth/2, m_SurfaceHeight,
            GL_COLOR_BUFFER_BIT, GL_LINEAR);
  glReadBuffer(GL_COLOR_ATTACHMENT3);
  glBlitFramebuffer(0, 0, m_RenderImage.width, m_RenderImage.height,
            m_SurfaceWidth/2, m_SurfaceHeight/2, m_SurfaceWidth, m_SurfaceHeight,
            GL_COLOR_BUFFER_BIT, GL_LINEAR);
}

最后呈现的效果是将四张图像渲染到一个屏幕上。

联系与交流

技术交流/获取源码可以添加我的微信:Byte-Flow ,进技术交流群


「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。

阿里云视频云@凡科快图.png

相关文章
|
5月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
55 0
|
存储 编解码 算法
Opengl ES之LUT滤镜(上)
Opengl ES之连载系列
343 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
221 0
|
数据安全/隐私保护 索引
Opengl ES之纹理数组
Opengl ES连载系列
180 0
|
数据安全/隐私保护
Opengl ES之水印贴图
Opengl ES之连载系列
88 0
|
Java 数据安全/隐私保护 Android开发
Opengl ES之矩阵变换(下)
Opengl ES连载系列
84 0
|
Java API 数据安全/隐私保护
Opengl ES之矩阵变换(上)
Opengl ES连载系列
87 0
|
存储
Opengl ES之踩坑记
Opengl ES之连载系列
91 0
|
存储 编解码 算法
Opengl ES之RGB转NV21
Opengl ES连载系列
117 0
|
并行计算 C++
Opengl ES之YUV数据渲染
Opengl ES连载系列
131 0