OpenGL ES 多目标渲染(MRT)
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)相关推荐
- Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据
系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...
- Android OpenGL ES 学习(十一) –渲染YUV视频以及视频抖音特效
OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...
- OpenGL/OpenGL ES入门:渲染YUV数据实践
纹理:GPU中的一块数据结构,YUV数据先经过采样,转成rgb显示. 着色器代码,先通过compile编译成GPU能识别的机器语言,再交由GPU进行显示. shader着色器,texture纹理,Ut ...
- Android OpenGL ES 离屏渲染(offscreen render)
通常在Android上使用OpenGL ES,都是希望把渲染后的结果显示在屏幕上,例如图片处理.模型显示等.这种情况下,只需要使用Android API中提供的GLSurfaceView类和Rende ...
- OpenGL ES之GLSL渲染图片显示的整体流程
整体思路 本文不采用UIKit的GLKBaseEffect渲染一张图片的显示,而是使用编译链接自定义的着色器(shader).用GLSL语言来实现自定义顶点/片元着色器,并将图形进行简单的渲染显示. ...
- OpenGL ES之3D渲染旋转的贴图立方体
效果展示 绘制流程 一.OpenGL ES 初始化 ① 初始化上下文并设置当前上下文 /* 初始化上下文并设置当前上下文* EAGLContext 是苹果iOS平台下实现OpenGLES 渲染层* k ...
- OpenGL ES 帧缓冲区位块传送(Blit)
该原创文章首发于微信公众号:字节流动 上文 OpenGL ES 多目标渲染(MRT) 中我们了解了利用 MRT 技术可以一次渲染到多个缓冲区,本文将利用帧缓冲区位块传送实现高性能缓冲区之间的像素拷贝. ...
- OpenGL ES之基本简介和渲染流程
简介 OpenGL ES (OpenGL for Embedded Systems) 是以⼿持和嵌入式为目标的高级3D图形应用程序编程接口(API). OpenGL ES是目前智能手机中占据统治地位的 ...
- 【OpenGL ES】OpenGL ES简介
[参考-khronos]https://www.khronos.org/opengles/ 1.简介 OpenGL ES(OpenGL for Embeded System)是OpenGL(Open ...
最新文章
- linux 12541 重启监听器,ORA-12541:ORA-12541:TNS:没有监听器 解决方法
- mysql 按照指定字段拼接_mysql 根据某个字段将多条记录的某个字段拼接成一个字段...
- SAP根据用户名查姓名
- python 钉钉消息推送_python3实现钉钉消息推送的方法示例
- 利用 FFmpeg palettegen paletteuse 生成接近全色的 gif 动画
- 部署和调优 1.3 pureftp部署和优化-1
- 【JQuery】初始化页面当异步加载时构建页面元素的顺序
- 第3章 Linux内核调试手段之三
- seo自动发外链_一套节约成本全网营销方案-小小课堂SEO培训教程
- c语言 已知某系统在通信联络中,数据结构(习题)..doc
- 本地计算机用plsql访问虚拟机中的oracle数据库
- hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新
- Composer基础应用1
- 数字电路与逻辑设计之集成触发器
- 2022华为机试真题 C++ 实现【事件推送】
- network attached storage 的简称,中文称为网络附加存储
- 手机b站封面提取网站_二次元之家 视频网站B站上海与北京办公设计欣赏
- 清理工作区git clean -fd
- 数据类型与堆栈内存练习数据类型检测
- 【ROS】在 Ubuntu 20.04 安装 ROS 的详细教程
热门文章
- 计算机网络蓝牙技术论文,《蓝牙技术及其应用》》-毕业论文.doc
- 计算机如何恢复原来用户,怎么一键还原,教您怎样还原电脑系统
- 搜狐快站创建的个人站点域名如何绑定自己的独立域名
- 三星s5 安装android,三星galaxy s5安装不了第三方软件怎么办?如何解决
- 联邦学习FATE框架安装搭建
- keepAlive详细操作
- 2021-2027全球与中国车载低噪音放大器市场现状及未来发展趋势
- IEEE投稿期刊推荐
- 新手上路 Vue腾讯云开发实战项目 问卷调查
- java电子面单开发_电子面单 - 无需录单提供快递发货,接口返回html快递模板及单号 – 基于ThinkPHP和Bootstrap的极速后台开发框架...