OpenGL ES 多目标渲染

OpenGL ES 多目标渲染

OpenGL ES 多目标渲染(MRT),即多重渲染目标,是 OpenGL ES 3.0 新特性,它允许应用程序一次渲染到多个缓冲区。

利用 MRT 技术,片段着色器可以输出多个颜色,可以用于保存 RGBA 颜色、 法线、 深度信息或者纹理坐标,每个颜色连接一个颜色缓冲区。

就目前接触的 MRT 技术,在图形图像算法中比较常用,主要用于获取算法中间结果、底图或者 Mask ,也用于多种高级渲染算法中,例如延迟着色和快速环境遮蔽估算。

使用 MRT 技术,一般需要为帧缓冲区对象(FBO)的设置多个颜色附着。FBO(Frame Buffer Object)即帧缓冲区对象,实际上是一个可添加缓冲区的容器,可以为其添加纹理或渲染缓冲区对象(RBO)。

FBO 帧缓冲区对象

FBO 本身不能用于渲染,只有添加了纹理或者渲染缓冲区之后才能作为渲染目标,它提供了 3 种附着(Attachment),分别是颜色附着、深度附着和模板附着。

本文为演示 MRT 技术的使用,为 FBO 的颜色附着设置 4 个纹理,一个纹理作为一个颜色附着(颜色缓冲区)。

const GLenum attachments[ATTACHMENT_NUM] = {GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1,GL_COLOR_ATTACHMENT2,GL_COLOR_ATTACHMENT3
};//生成帧缓冲区对象
glGenFramebuffers(1, &m_FBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);//生成 4 个纹理
glGenTextures(ATTACHMENT_NUM, m_AttachTexIds);
for (int i = 0; i < ATTACHMENT_NUM; ++i) {glBindTexture(GL_TEXTURE_2D, m_AttachTexIds[i]);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachments[i], GL_TEXTURE_2D, m_AttachTexIds[i], 0);
}//告诉 OpenGL ,我要渲染到 4 个颜色附着上
glDrawBuffers(ATTACHMENT_NUM, attachments);if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_FRAMEBUFFER))
{return false;
}

本文使用 MRT 技术对应的顶点和片段着色器如下,我们使用了 4 个纹理作为颜色附着,其中直接渲染原图到第一个纹理,分别渲染 RGB 三个通道的图像到另外三个纹理,然后再利用另外一个着色器将 4 个纹理的结果渲染到屏幕上。

#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_texCoord;
out vec2 v_texCoord;
void main()
{gl_Position = a_position;v_texCoord = a_texCoord;
}#version 300 es
precision mediump float;
in vec2 v_texCoord;
//分别对应 4 个绑定的纹理对象,将渲染结果保存到 4 个纹理中
layout(location = 0) out vec4 outColor0;
layout(location = 1) out vec4 outColor1;
layout(location = 2) out vec4 outColor2;
layout(location = 3) out vec4 outColor3;
uniform sampler2D s_Texture;
void main()
{vec4 outputColor = texture(s_Texture, v_texCoord);outColor0 = outputColor;outColor1 = vec4(outputColor.r, 0.0, 0.0, 1.0);outColor2 = vec4(0.0, outputColor.g, 0.0, 1.0);outColor3 = vec4(0.0, 0.0, outputColor.b, 1.0);
}

用于渲染(采样) 4 个纹理的片段着色器,实际上是将 4 张图做一个拼接。

#version 300 es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D s_Texture0;
uniform sampler2D s_Texture1;
uniform sampler2D s_Texture2;
uniform sampler2D s_Texture3;
void main()
{if(v_texCoord.x < 0.5 && v_texCoord.y < 0.5){   outColor = texture(s_Texture0, v_texCoord);}else if(v_texCoord.x > 0.5 && v_texCoord.y < 0.5){outColor = texture(s_Texture1, v_texCoord);}else if(v_texCoord.x < 0.5 && v_texCoord.y > 0.5){outColor = texture(s_Texture2, v_texCoord);}else{outColor = texture(s_Texture3, v_texCoord);}
}

首先获取当前默认帧缓冲区的 id ,然后绑定我们新创建的 FBO 渲染,渲染完成再绑定默认帧缓冲区对象,使用另外一个着色器程序渲染四张纹理图。

//首先获取当前默认帧缓冲区的 id
GLint defaultFrameBuffer = GL_NONE;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFrameBuffer);//绑定我们新创建的 FBO 渲染
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
glViewport ( 0, 0, m_RenderImage.width, m_RenderImage.height);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffers(ATTACHMENT_NUM, attachments);//使用渲染输出到 4 个纹理的着色器程序
glUseProgram (m_MRTProgramObj);
glBindVertexArray(m_VaoId);
UpdateMVPMatrix(m_MVPMatrix, 180, 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);
//渲染(采样) 4 个纹理的着色器程序
glUseProgram (m_ProgramObj);
UpdateMVPMatrix(m_MVPMatrix, 0, m_AngleY, (float)screenW / screenH);
glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);//指定 4 个纹理作为输入
for (int i = 0; i < ATTACHMENT_NUM; ++i)
{glActiveTexture(GL_TEXTURE0 + i);glBindTexture(GL_TEXTURE_2D, m_AttachTexIds[i]);char samplerName[64] = {0};sprintf(samplerName, "s_Texture%d", i);GLUtils::setInt(m_ProgramObj, samplerName, i);
}glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);

OpenGL ES 多目标渲染结果。

OpenGL ES 多目标渲染

OpenGL ES 多目标渲染(MRT)相关推荐

  1. Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  2. Android OpenGL ES 学习(十一) –渲染YUV视频以及视频抖音特效

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...

  3. OpenGL/OpenGL ES入门:渲染YUV数据实践

    纹理:GPU中的一块数据结构,YUV数据先经过采样,转成rgb显示. 着色器代码,先通过compile编译成GPU能识别的机器语言,再交由GPU进行显示. shader着色器,texture纹理,Ut ...

  4. Android OpenGL ES 离屏渲染(offscreen render)

    通常在Android上使用OpenGL ES,都是希望把渲染后的结果显示在屏幕上,例如图片处理.模型显示等.这种情况下,只需要使用Android API中提供的GLSurfaceView类和Rende ...

  5. OpenGL ES之GLSL渲染图片显示的整体流程

    整体思路 本文不采用UIKit的GLKBaseEffect渲染一张图片的显示,而是使用编译链接自定义的着色器(shader).用GLSL语言来实现自定义顶点/片元着色器,并将图形进行简单的渲染显示. ...

  6. OpenGL ES之3D渲染旋转的贴图立方体

    效果展示 绘制流程 一.OpenGL ES 初始化 ① 初始化上下文并设置当前上下文 /* 初始化上下文并设置当前上下文* EAGLContext 是苹果iOS平台下实现OpenGLES 渲染层* k ...

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

    该原创文章首发于微信公众号:字节流动 上文 OpenGL ES 多目标渲染(MRT) 中我们了解了利用 MRT 技术可以一次渲染到多个缓冲区,本文将利用帧缓冲区位块传送实现高性能缓冲区之间的像素拷贝. ...

  8. OpenGL ES之基本简介和渲染流程

    简介 OpenGL ES (OpenGL for Embedded Systems) 是以⼿持和嵌入式为目标的高级3D图形应用程序编程接口(API). OpenGL ES是目前智能手机中占据统治地位的 ...

  9. 【OpenGL ES】OpenGL ES简介

    [参考-khronos]https://www.khronos.org/opengles/ 1.简介 OpenGL ES(OpenGL for Embeded System)是OpenGL(Open ...

最新文章

  1. linux 12541 重启监听器,ORA-12541:ORA-12541:TNS:没有监听器 解决方法
  2. mysql 按照指定字段拼接_mysql 根据某个字段将多条记录的某个字段拼接成一个字段...
  3. SAP根据用户名查姓名
  4. python 钉钉消息推送_python3实现钉钉消息推送的方法示例
  5. 利用 FFmpeg palettegen paletteuse 生成接近全色的 gif 动画
  6. 部署和调优 1.3 pureftp部署和优化-1
  7. 【JQuery】初始化页面当异步加载时构建页面元素的顺序
  8. 第3章 Linux内核调试手段之三
  9. seo自动发外链_一套节约成本全网营销方案-小小课堂SEO培训教程
  10. c语言 已知某系统在通信联络中,数据结构(习题)..doc
  11. 本地计算机用plsql访问虚拟机中的oracle数据库
  12. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新
  13. Composer基础应用1
  14. 数字电路与逻辑设计之集成触发器
  15. 2022华为机试真题 C++ 实现【事件推送】
  16. network attached storage 的简称,中文称为网络附加存储
  17. 手机b站封面提取网站_二次元之家 视频网站B站上海与北京办公设计欣赏
  18. 清理工作区git clean -fd
  19. 数据类型与堆栈内存练习数据类型检测
  20. 【ROS】在 Ubuntu 20.04 安装 ROS 的详细教程

热门文章

  1. 计算机网络蓝牙技术论文,《蓝牙技术及其应用》》-毕业论文.doc
  2. 计算机如何恢复原来用户,怎么一键还原,教您怎样还原电脑系统
  3. 搜狐快站创建的个人站点域名如何绑定自己的独立域名
  4. 三星s5 安装android,三星galaxy s5安装不了第三方软件怎么办?如何解决
  5. 联邦学习FATE框架安装搭建
  6. keepAlive详细操作
  7. 2021-2027全球与中国车载低噪音放大器市场现状及未来发展趋势
  8. IEEE投稿期刊推荐
  9. 新手上路 Vue腾讯云开发实战项目 问卷调查
  10. java电子面单开发_电子面单 - 无需录单提供快递发货,接口返回html快递模板及单号 – 基于ThinkPHP和Bootstrap的极速后台开发框架...