当前位置:网站首页>OpenGLES 学习之帧缓存
OpenGLES 学习之帧缓存
2022-08-04 05:25:00 【vivianluomin】
什么是帧缓冲区
帧缓冲区(framebuffer object)简称 FBO,用于写入颜色值,写入深度信息和深度缓冲和允许我们根据一些条件丢弃特定片段的模板缓冲。
图像在绘制时最终都是绘制到帧缓冲区中的,一般情况下我们都是使用的是默认FBO,也就是我们的屏幕,也就是着色器各方面绘制结果存储的逻辑对象。
使用方式
1. 创建帧缓冲区
使用glGenFramebuffers 来创建一个帧缓冲对象
unsigned int framebuffer;
glGenFramebuffers(1,&framebuffer);
然后使用glBindFramebuffer 来绑定帧缓冲对象,这个意思表示为将这个帧缓冲对象是激活的,之后的读写帧缓冲的操作都会使用我们绑定的这个FBO
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
如果要解绑定的话,也就是恢复到默认缓冲区
glBindFramebuffer(GL_FRAMEBUFFER,0);
2. 为缓冲区添加附件
一个完整的帧缓冲区需要满足如下的条件:
- 附加至少一个缓冲(颜色,深度/模板缓冲)
- 至少有一个颜色附件
- 所有的附件都必须是完整的
- 每个缓冲都应该有相同的样本数
2.1 添加一个纹理附件
把一个纹理附件添加到缓冲区后,之后所有的渲染指令都被写入这个纹理之中,可以把它当作一个普通的颜色/深度或模板缓冲一样
glGenTextures(1,&texColorBuffer); //创建纹理
glBindTexture(GL_TEXTURE_2D,texColorBuffer);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,800,600,0,GL_RGB,GL_UNSIGNED_BYTE,0);//最后一个参数为0表示仅仅分配内存但是没有填充
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texColorBuffer,0);//附加到帧缓冲区上
3. 进行渲染
在渲染前绑定你的FBO,调用渲染指令将效果渲染到纹理
glViewport(0,0,800,600);
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,texture2);
glUseProgram(program);
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
//glDrawArrays(GL_TRIANGLES,0,6);
glBindFramebuffer(GL_FRAMEBUFFER,0);
示例 渲染两张图片叠加上屏
首先在准备好两张图片
在进行相关的opengl shader和program初始化后,加载图片数据到两张纹理中:
ShaderManager *shaderManager = new ShaderManager();
shaderManager->initVertexData(nullptr);
shaderManager->loadShader();
shaderManager->createProgram();
shaderManager->loadImage();
void ShaderManager::loadImage()
{
int img_width;
int img_height;
int img_nrChannels;
unsigned char *img_data;
stbi_set_flip_vertically_on_load(true);
img_data = stbi_load("/Users/bytedance/Desktop/container.jpg",&img_width,&img_height,&img_nrChannels,0);
if(img_data == NULL){
std::cout<<"can not get image data"<<std::endl;
}
std::cout<<"image width-height: "<<img_width<<"-"<<img_height<<std::endl;
glGenTextures(1,&texture1);
glBindTexture(GL_TEXTURE_2D,texture1);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
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_RGB,img_width,img_height,0,GL_RGB,GL_UNSIGNED_BYTE,img_data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(img_data);
unsigned char *data2 = stbi_load("/Users/bytedance/Desktop/awesomeface.png",&img_width,&img_height,&img_nrChannels,0);
if(data2 == NULL){
std::cout<<"can not get image2 data"<<std::endl;
}
std::cout<<"image width-height: "<<img_width<<"-"<<img_height<<std::endl;
glGenTextures(1,&texture2);
glBindTexture(GL_TEXTURE_2D,texture2);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
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,img_width,img_height,0,GL_RGBA,GL_UNSIGNED_BYTE,data2);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data2);
}
之后得到你的shader相关需要进行采样的纹理对象的位置:
void ShaderManager::initLocationValue(bool screen)
{
glUseProgram(program);
if(!screen){
glUniform1i(glGetUniformLocation(program,"texture1"),0);
glUniform1i(glGetUniformLocation(program,"texture2"),1);
} else{
glUniform1i(glGetUniformLocation(program,"screenTexture"),0);
}
}
然后创建帧缓冲区,绑定纹理:
void ShaderManager::createFrameBuffer()
{
glGenFramebuffers(1,&framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
glGenTextures(1,&texColorBuffer);
glBindTexture(GL_TEXTURE_2D,texColorBuffer);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,800,600,0,GL_RGB,GL_UNSIGNED_BYTE,0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texColorBuffer,0);
// unsigned int rbo;
// glGenRenderbuffers(1, &rbo);
// glBindRenderbuffer(GL_RENDERBUFFER, rbo);
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600); // use a single renderbuffer object for both a depth AND stencil buffer.
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it
glBindTexture(GL_TEXTURE_2D,0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
之后进行渲染:
这样就将这两张纹理混合后的结果保存到了帧缓冲区中
void ShaderManager::render()
{
glViewport(0,0,800,600);
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,texture2);
glUseProgram(program);
glClearColor(1.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
//glDrawArrays(GL_TRIANGLES,0,6);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}
最后再渲染上屏:
ShaderManager *screen = new ShaderManager();
screen->initScreenData();
screen->loadShader(vs,fs);
screen->createProgram();
screen->render_to_screen(shaderManager->texColorBuffer);
结果:红色背景为我们申请的帧缓冲区的背景,黄色背景为默认缓冲区的背景
边栏推荐
- Embedded system driver primary [3] - _IO model in character device driver foundation
- Landing, the IFC, GFC, FFC concept, layout rules, forming method, use is analysed
- Interesting Kotlin 0x0E: DeepRecursiveFunction
- 4.2 Declarative Transaction Concept
- 代码重构:面向单元测试
- Unity表格配置编辑工具
- 【论文阅读笔记】无监督行人重识别中的采样策略
- static在不同位置定义变量居然还有不同的含义?
- 3面头条,花7天整理了面试题和学习笔记,已正式入职半个月
- Web Basics and Exercises for C1 Certification - My Study Notes
猜你喜欢
随机推荐
8.03 Day34---BaseMapper查询语句用法
动态规划总括
warning C4251: “std::vector&lt;_Ty&gt;”需要有 dll 接口由 class“Test”的客户端使用错误
即时通讯网 即时通讯音视频开发
8. Custom mapping resultMap
7.18 Day23----标记语言
[Evaluation model] Topsis method (pros and cons distance method)
How to view sql execution plan offline collection
4.3 Annotation-based declarative transactions and XML-based declarative transactions
Interesting Kotlin 0x0E: DeepRecursiveFunction
7.16 Day22---MYSQL(Dao模式封装JDBC)
你以为border-radius只是圆角吗?【各种角度】
渗透测试(PenTest)基础指南
自动化测试的成本高效果差,那么自动化测试的意义在哪呢?
flink cdc一启动,源端Oracle那台服务器的CPU就飙升到80%以上,会是啥原因呢?
JS基础--强制类型转换(易错点,自用)
el-Select selector bottom fixed
Typora 使用保姆级教程 | 看这一篇就够了 | 历史版本已被禁用
力扣:63. 不同路径 II
What are the functions of mall App development?









