wayland(xdg_wm_base) + egl + opengles 使用FBO渲染到纹理实例(六)

文章目录

  • 前言
  • 一、FBO介绍
    • 1. FBO 简介
    • 2. FBO的关键组成部分
    • 3. FBO的基本工作流程
    • 4. FBO 实现渲染到纹理
    • 5. FBO 实现离屏渲染
  • 二、FBO 实现渲染到纹理的代码实例
    • 1. egl_wayland_texture3_2.c
    • 2. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
    • 3. 编译
    • 4. 运行
  • 总结
  • 参考资料


前言

本文主要介绍 如何在 opengles 中使用FBO 实现渲染到纹理的功能
软硬件环境:
硬件:PC
软件:ubuntu22.04 opengles3.0 egl1.4


一、FBO介绍

1. FBO 简介

FBO(Framebuffer Object)是OpenGL的一个扩展,它允许我们将渲染结果直接绘制到一个纹理或者渲染缓冲对象中,而不是默认的帧缓冲。

使用FBO可以实现一些高级的渲染技术,如离屏渲染、后期处理、抗锯齿等。它提供了一个独立于窗口的帧缓冲对象,可以将渲染的结果存储到纹理或者渲染缓冲对象中,并且可以在后续的渲染中作为输入来进行处理。

2. FBO的关键组成部分

  1. Color Attachment:用于存储颜色信息的附件,可以是纹理或者渲染缓冲对象;
  2. Depth Attachment:用于存储深度信息的附件,也可以是纹理或者渲染缓冲对象;
  3. Stencil Attachment:用于存储模板信息的附件,同样可以是纹理或者渲染缓冲对象;

3. FBO的基本工作流程

  1. 创建一个FBO并绑定到OpenGLES上下文;
  2. 创建并绑定颜色附件、深度附件和模板附件;
  3. 进行渲染操作,绘制到FBO中的附件;
  4. 在需要时,将FBO的附件纹理或者渲染缓冲对象用作输入进行后续处理;
  5. 最后,将FBO解绑并恢复默认的帧缓冲;

4. FBO 实现渲染到纹理

如果纹理被附着到 FBO 的颜色缓冲区就可以实现渲染到纹理,FBO实现离屏渲染的步骤如下:

  1. 创建一个FBO对象,将其绑定到OpenGLES上下文中;
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  1. 创建一个纹理对象,并将其绑定为FBO的颜色附件;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);      //这里最后一个参数是NULL ,很重要
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, texture, 0);         //GL_COLOR_ATTACHMENT0是FBO的颜色附件,它是一个内置枚举常量,指定了FBO中可用的颜色附件的编号。在OpenGLES中,可以将多个颜色附件绑定到同一个FBO上,使用GL_COLOR_ATTACHMENT0、GL_COLOR_ATTACHMENT1、GL_COLOR_ATTACHMENT2等常量来分别表示不同的颜色附件
  1. 为FBO创建一个深度附件或者模板附件,如果需要的话(在这里这一步可以不需要,只用到了颜色附件)
GLuint depthBuffer;
glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
  1. 检查FBO帧缓冲的完整性
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
   
    // 帧缓冲不完整,处理错误
}
  1. 进行渲染到纹理操作,即在FBO上进行渲染绘制
// 渲染之前需要将FBO绑定
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// 渲染操作
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 进行绘制操作

// 渲染结束后需要将FBO解绑
glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1. 将渲染结果从FBO中读取到CPU内存或进行纹理贴图上屏显示
// 读取FBO中的颜色附件数据到CPU内存
glReadBuffer(GL_COLOR_ATTACHMENT0);
GLubyte* data = new GLubyte[width * height * 4];
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

// 渲染到屏幕
glBindFramebuffer(GL_FRAMEBUFFER, 0);                //FBO解绑
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置顶点和纹理坐标数组
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vtexcoords);
glEnableVertexAttribArray(1);

textureLocation = glGetUniformLocation(shaderProgram, "uTexture");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureLocation, 0);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1. 在完成所有的操作后,需要释放FBO和相关的附件资源
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);

5. FBO 实现离屏渲染

如果渲染缓冲区对象RBO被附着到 FBO 的颜色缓冲区, 就可以实现离屏渲染,离屏渲染的步骤同渲染到纹理的步骤类似:

  1. 创建一个FBO对象,将其绑定到OpenGLES上下文中;
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  1. 创建一个渲染缓冲对象RBO,并将其绑定为FBO的颜色附件;
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
  1. 为FBO创建一个深度附件或者模板附件,如果需要的话(在这里这一步可以不需要,只用到了颜色附件);
  2. 检查帧缓冲FBO的完整性;
  3. 进行渲染操作,将渲染结果存储到渲染缓冲对象中;
  4. 渲染完成后,解绑帧缓冲对象;

二、FBO 实现渲染到纹理的代码实例

以下代码实例实现了渲染到纹理到效果,将纯蓝色的图像渲染到一个640x480 大小的纹理中,然后将该纹理进行纹理贴图操作上屏显示;

1. egl_wayland_texture3_2.c

代码如下(示例):

#include 
#include 
#include 
#include 
#include 

你可能感兴趣的:(weston/wayland,EGL/OpenGL,ES,opengles,egl,wayland)