最新七、帧缓冲离屏渲染,2024年最新从不一样的角度描述C C++事件传递

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取


调用`glRenderbufferStorage`函数可以创建一个深度和模板渲染缓冲对象:



glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
创建一个渲染缓冲对象与创建纹理对象相似,不同之处在于这个对象是专门被设计用于图像的,而不是通用目的的数据缓冲,比如纹理。这里我们选择GL_DEPTH24_STENCIL8作为内部格式,它同时代表24位的深度和8位的模板缓冲。


帧缓冲对象附加



glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);


对比渲染缓冲区对象和纹理附加:貌似RBO比纹理有点多,但也不是万能的,纹理自有纹理的优点,纹理能够在shader中进行操作或者需要读取像素时,做一些处理,此时RBO就无能为力了。


#### 5)介绍三个顶点


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WZWv2r4s-1686050452791)(C:\Users\CreatWall\_zhouwen\Desktop\pic\pic\zuobiao.png)]


**真实验证这个好像有些问题,如果按这个顶点编写,最后离屏渲染出来的图形是反的。**


黑色表现显示的内容矩形


红色坐标表示**顶点坐标**[一般单位为0.5]


黄色坐标表示**正常纹理坐标**,原点在左上角【一般单位为1】


蓝色坐标表示**FBO的纹理坐标**,原点为左下角【一般单位为1】


紫色的描述表示**索引**,012,132.三角形凑矩形


### 第二部分编写代码


主要是C++这边的代码;


因为工程完成了使用离屏渲染操作后还将结果显示了,所以这边是需要创建两个opengles的工程的CreateGLProgram。然后主要是围绕这两个工程来实现的。


m\_ProgramObj普通工程:与之前纹理工程一致,需要绑定VAO,VBO以及创建绑定纹理,注意最后绘画的时候绑定离屏渲染的那个纹理进行显示。


m\_FboProgramOb离屏渲染的工程:跟普通工程差不多,只是创建绑定纹理那里暂时不需要绑定数据。还有需要创建FBO帧缓冲这块。与普通工程有不同的片段着色器代码,这块离屏渲染可以做一些特殊操作,当前工程就是将图片灰度画。


#### 1)GLUtil.h文件将创建着色器和创建工程接口抽象化



//
// Created by CreatWall_zhouwen on 2023/4/21.
//

#ifndef FORTHDRAWFBO_GLUTIL_H
#define FORTHDRAWFBO_GLUTIL_H

#include “Util.h”
#include <GLES3/gl3.h>
#define TAG “GLUTIL_H”

void CheckGLerror(GLuint shader, GLenum pname, GLint *params)
{
glGetShaderiv(shader, pname, params);
}

GLuint LoadShader(GLenum shaderType, const char *pSource)
{
LOGD(“LoadShader Entern”);
//创建对应类型的着色器
GLuint ShaderHandle = glCreateShader(shaderType);//创建shaderType类型的着色器
if (ShaderHandle)
{
//附加着色器源码
glShaderSource(ShaderHandle, 1, &pSource, NULL);//shader源码为pSource
//编译着色器
glCompileShader(ShaderHandle);
//获取编译结果是否成
GLint compiled = 0;
glGetShaderiv(ShaderHandle, GL_COMPILE_STATUS, &compiled);
if (!compiled){
glDeleteShader(ShaderHandle);
LOGD(“glCompileShader ShaderHandle error”);
return 0;
}
}
LOGD(“LoadShader Leave”);
return ShaderHandle;
}

GLuint CreateGLProgram(const char *pVertexShaderSource, const char *pFragShaderSource, GLuint &vertexShaderHandle, GLuint &fragShaderHandle)
{
LOGD(“CreateProgram Entern”);

GLuint program = 0;
GLint AttachStatus = GL_FALSE;
//创建顶点着色器
vertexShaderHandle = LoadShader(GL_VERTEX_SHADER, pVertexShaderSource);
if (!vertexShaderHandle) return program;
LOGD("vertexShaderHandle success");

//创建片段着色器
fragShaderHandle = LoadShader(GL_FRAGMENT_SHADER, pFragShaderSource);
if (!fragShaderHandle) return program;
LOGD("fragShaderHandle success");

//创建程序
program = glCreateProgram();
if (program)
{
    AttachStatus = 0;
    glAttachShader(program, vertexShaderHandle);
    glGetShaderiv(vertexShaderHandle, GL_ATTACHED_SHADERS, &AttachStatus);
    if(AttachStatus != 0 ){
        LOGD("glAttachShader vertexShaderHandle error %d",AttachStatus);
        return 0;
    }
    AttachStatus = 0;
    glAttachShader(program, fragShaderHandle);
    glGetShaderiv(fragShaderHandle, GL_ATTACHED_SHADERS, &AttachStatus);
    if(AttachStatus != 0 ){
        LOGD("glAttachShader fragShaderHandle error %d",AttachStatus);
        return 0;
    }

    glLinkProgram(program);
    GLint linkStatus = GL_FALSE;
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    if (linkStatus != GL_TRUE){
        LOGD("glLinkProgram error AttachStatus = %d", linkStatus);
        glDeleteProgram(program);
        program = 0;
        return 0;
    }
    glDetachShader(program, vertexShaderHandle);
    glDeleteShader(vertexShaderHandle);
    vertexShaderHandle = 0;
    glDetachShader(program, fragShaderHandle);
    glDeleteShader(fragShaderHandle);
    fragShaderHandle = 0;
    LOGD("glCreateProgram success");
}
LOGD("CreateProgram Leave");
return program;

}

#endif //FORTHDRAWFBO_GLUTIL_H


#### 2)离屏渲染操作类


FBOSample.h



//
// Created by CreatWall_zhouwen on 2023/4/21.
//

#ifndef FORTHDRAWFBO_FBOSAMPLE_H
#define FORTHDRAWFBO_FBOSAMPLE_H
#include <GLES3/gl3.h>

class FBOSample {
public:
FBOSample();
~FBOSample();
void CreateProgram(const char *ver, const char *frag, const char * fragfbo);//创建工程并初始化
void getTexturedata(unsigned char data, int width, int height);//从NDK那边获取图片数据传过来
void OnSurfaceChanged(int width, int height);//获取屏幕大小
static FBOSample
GetInstance();
static void DestroyInstance();
void Draw();//绘画 就是执行离屏渲染再将离屏渲染的结果显示
private:
GLuint m_FboVertexShader;//FBO的顶点着色器和片段着色器
GLuint m_FboFragmentShader;
GLuint m_VertexShader;//普通渲染的顶点着色器和片段着色器
GLuint m_FragmentShader;
GLuint m_ProgramObj;//普通工程ID
GLuint m_FboProgramObj;//FBO工程ID
GLuint m_ImageTextureId;//图片数据的纹理ID
GLuint m_FboTextureId;//FBO绑定的空数据纹理ID
GLint m_SamplerLoc;//普通片段着色器中的采样器值的位置
GLint m_FboSamplerLoc;//FBO片段着色器中的采样器值的位置
GLuint m_FboId;//FBO的ID
unsigned char *texturedata;
int texturewidth, textureheight;
GLuint m_VaoIds[2];//存放顶点数据 0表示普通渲染的顶点缓冲区 1表示离屏渲染的顶点缓冲区
GLuint m_VboIds[4];//0表示顶点坐标缓冲区,1表示普通纹理坐标缓冲区,2表示离屏渲染纹理坐标缓冲区,3表示纹理索引坐标缓冲区

int srceenWidth, srceenHeight;//屏幕宽高

};

#endif //FORTHDRAWFBO_FBOSAMPLE_H


FBOSample.cpp



//
// Created by CreatWall_zhouwen on 2023/4/21.
//

#include “FBOSample.h”
#include “Util.h”
#include “GLUtil.h”
FBOSample* m_pContext = nullptr;
#define TAG “DRAWTEXTURE”
//顶点坐标
GLfloat vVertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};

//正常纹理坐标
GLfloat vTexCoors[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};

//fbo 纹理坐标与正常纹理方向不同 实践并不相反
GLfloat vFboTexCoors[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};

GLushort indices[] = { 0, 1, 2, 1, 3, 2 };//三角形的索引数组

FBOSample::FBOSample() {
m_VaoIds[0] = GL_NONE;
m_VboIds[0] = GL_NONE;

m_ImageTextureId = GL_NONE;
m_FboTextureId = GL_NONE;
m_SamplerLoc = GL_NONE;
m_FboId = GL_NONE;
m_FboProgramObj = GL_NONE;
m_FboVertexShader = GL_NONE;
m_FboFragmentShader = GL_NONE;
m_FboSamplerLoc = GL_NONE;

}

FBOSample::~FBOSample() {
if (m_ProgramObj)
{
glDeleteProgram(m_ProgramObj);
}

if (m_FboProgramObj)
{
    glDeleteProgram(m_FboProgramObj);
}

if (m_ImageTextureId)
{
    glDeleteTextures(1, &m_ImageTextureId);
}

if (m_FboTextureId)
{
    glDeleteTextures(1, &m_FboTextureId);
}

if (m_VboIds[0])
{
    glDeleteBuffers(4, m_VboIds);
}

if (m_VaoIds[0])
{
    glDeleteVertexArrays(2, m_VaoIds);
}

if (m_FboId)
{
    glDeleteFramebuffers(1, &m_FboId);
}

}

void FBOSample::CreateProgram(const char *ver, const char *frag, const char * fragfbo) {
LOGD(“CreateProgram Enter”);
// 编译链接用于普通渲染的着色器程序
m_ProgramObj = CreateGLProgram(ver, frag, m_VertexShader, m_FragmentShader);
// 编译链接用于离屏渲染的着色器程序
m_FboProgramObj = CreateGLProgram(ver, fragfbo, m_FboVertexShader, m_FboFragmentShader);
if (m_ProgramObj == GL_NONE || m_FboProgramObj == GL_NONE)
{
LOGD(“FBOSample::Init m_ProgramObj == GL_NONE”);
return;
}
LOGD(“CreateGLProgram Success”);
//获取片段着色器中s_TextureMap的属性位置,编译后期指定是哪个纹理
m_SamplerLoc = glGetUniformLocation(m_ProgramObj, “s_TextureMap”);
m_FboSamplerLoc = glGetUniformLocation(m_FboProgramObj, “s_TextureMap”);
LOGD(“glGetUniformLocation Success”);
//生成VBO 加载顶点数据和索引数据
glGenBuffers(4, m_VboIds);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vTexCoors), vTexCoors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vFboTexCoors), vFboTexCoors, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[3]);//最后一个为纹理的索引缓冲数据
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
LOGD(“glGenBuffers Success”);
// 生成 2 个 VAO顶点数据对象,一个用于普通渲染,另一个用于离屏渲染
glGenVertexArrays(2, m_VaoIds);
//初始化用于普通渲染
glBindVertexArray(m_VaoIds[0]);//绑定0顶点缓冲区 那么接下来的操作就是绑定0顶点缓冲区的初始化
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);//绑定属性缓冲区0并设置顶点数据属性
glEnableVertexAttribArray(0);//0对应的顶点着色器的location
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[1]);//绑定属性缓冲区1并设置纹理坐标数据属性
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[3]);//绑定属性缓冲区3并设置纹理索引属性
glBindVertexArray(GL_NONE);
LOGD(“m_VaoIds[0] Success”);
//初始化离屏渲染的VAO
glBindVertexArray(m_VaoIds[1]);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[2]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const void *)0);
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[3]);

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

GL_ARRAY_BUFFER, GL_NONE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[3]);

[外链图片转存中…(img-7bfmpzEa-1715875918799)]
[外链图片转存中…(img-hkBLEx6P-1715875918800)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值