当前位置:网站首页>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);
结果:红色背景为我们申请的帧缓冲区的背景,黄色背景为默认缓冲区的背景
边栏推荐
- npm报错Beginning October 4, 2021, all connections to the npm registry - including for package installa
- Teenage Achievement Hackers Need These Skills
- 嵌入式系统驱动初级【3】——字符设备驱动基础中_IO模型
- DP4398:国产兼容替代CS4398立体声24位/192kHz音频解码芯片
- [Evaluation model] Topsis method (pros and cons distance method)
- leetcode 12. Integer to Roman numeral
- [Cocos 3.5.2]开启模型合批
- Canal mysql data synchronization
- FFmpeg源码分析:avformat_open_input
- [One step in place] Jenkins installation, deployment, startup (complete tutorial)
猜你喜欢

MySQL log articles, binlog log of MySQL log, detailed explanation of binlog log

少年成就黑客,需要这些技能

Can 't connect to MySQL server on' localhost3306 '(10061) simple solutions

在被面试官说了无数次后,终于潜下心来整理了一下JVM的类加载器

Tactile intelligent sharing - SSD20X realizes upgrade display progress bar

About yolo7 and gpu

读者让我总结一波 redis 面试题,现在肝出来了

嵌入式系统驱动初级【4】——字符设备驱动基础下_并发控制

Web Basics and Exercises for C1 Certification - My Study Notes

el-Select selector bottom fixed
随机推荐
Towards Real-Time Multi-Object Tracking (JDE)
MySql数据恢复方法个人总结
The Road to Ad Monetization for Uni-app Mini Program Apps: Full Screen Video Ads
Unity Visual Effect Graph入门与实践
C Expert Programming Chapter 4 The Shocking Fact: Arrays and Pointers Are Not the Same 4.5 Other Differences Between Arrays and Pointers
Programming hodgepodge (4)
Unity DOTS学习教程汇总
Plus版SBOM:流水线物料清单PBOM
力扣:96.不同的二叉搜索树
[Cloud Native--Kubernetes] Pod Resource Management and Probe Detection
Sublime Text 3 2021.8.3 个人配置
离线采集怎么看sql执行计划
在被面试官说了无数次后,终于潜下心来整理了一下JVM的类加载器
C Expert Programming Chapter 5 Thinking about Linking 5.2 Advantages of Dynamic Linking
7.13 Day20----MYSQL
[SemiDrive source code analysis] [MailBox inter-core communication] 47 - Analysis of RPMSG_IPCC_RPC mode limit size of single transmission and limit bandwidth test
Unity自动生成阻挡Collider的GameObject工具
入坑软件测试的经验与建议
【论文阅读笔记】无监督行人重识别中的采样策略
flink cdc一启动,源端Oracle那台服务器的CPU就飙升到80%以上,会是啥原因呢?