3. OpenGL综合知识---Frame Buffer

GPU的绘制结果并不一定直接写入on screen buffer中。On screen buffer中的数据是被用以显示输出的颜色信息,所以,on screen buffer属于color buffer。在OpenGL中定义了多个color buffer,比如front bufferback bufferleft buffer等等,其中front buffer就是on screen buffer

如果将GPU的绘制结果直接写入front buffer中,可能会出现闪烁现象。

可以将GPU的绘制结果先写入back buffer中,然后再用某种机制显示出来,比如在合适的时机将数据拷贝到front buffer中。这样,就可以消除闪烁现象。

 

GPU绘制结果除了颜色信息外,还可能包括depthstencil信息,假如存在的话,它们会被分别输出到depth buffersetncil buffer中。

 

所有的color bufferdepth bufferstencil bufferaccum buffer组成为Frame buffer,如下图所示。

 

4 

 

实际上,存在两种类型的Frame Buffer,一种类型就是如前所述,和on screen buffer相关联,最终要显示出来的;另一种类型则和on screen buffer无关,一般是作为中间结果暂存,不需要显示,在frame buffer object技术中被引入。一般所说的frame buffer都是以显示为目的的。

以后,我们将不再使用on screen buffer这个说法,而用frame buffer这个术语。

 

 

深入到驱动开发层次,有些显卡为了效率考虑,depth bufferstencil buffer在物理上可能是交叉在一起的。

如果是一个全屏程序,也就是说color buffer和屏幕分辨率是一致的,可以将back buffer中的数据拷贝到front buffer中进行显示,也可以直接将back buffer的属性设置为on screen buffer,这样减少拷贝过程可以大幅提高性能。

如果不是全屏程序,front buffer其实只是on screen buffer的一部分。

为了某些设计上的考虑,front buffer可能和on screen buffer在物理上是分开的,当然,驱动程序会对外屏蔽这个特性。

将一张图片渲染到frame buffer的颜色附件上,需要完成以下几个步骤: 1. 创建并绑定一个 frame buffer 对象。 2. 创建一个颜色缓存附件并将其附加到 frame buffer 上。 3. 将要渲染的图片绑定到纹理上。 4. 将纹理附加到颜色缓存附件上并进行渲染。 下面是具体的代码实现: ```c++ // 创建并绑定一个 frame buffer 对象 unsigned int FBO; glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); // 创建一个颜色缓存附件并将其附加到 frame buffer 上 unsigned int textureColorBuffer; glGenTextures(1, &textureColorBuffer); glBindTexture(GL_TEXTURE_2D, textureColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 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, textureColorBuffer, 0); // 检查 frame buffer 是否完整 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // 将要渲染的图片绑定到纹理上 unsigned int texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); 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); int width, height, nrChannels; unsigned char* data = stbi_load("image.jpg", &width, &height, &nrChannels, 0); if (data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { std::cout << "Failed to load texture" << std::endl; } stbi_image_free(data); // 将纹理附加到颜色缓存附件上并进行渲染 glBindFramebuffer(GL_FRAMEBUFFER, FBO); glViewport(0, 0, screenWidth, screenHeight); glUseProgram(shaderProgram); glBindVertexArray(VAO); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); ``` 在这段代码中,我们首先创建并绑定了一个 frame buffer 对象。然后,我们创建了一个颜色缓存附件并将其附加到 frame buffer 上。接下来,我们加载图片并将其绑定到纹理上。最后,我们将纹理附加到颜色缓存附件上并进行渲染。注意,在渲染结束后,我们需要将 frame buffer 解绑,否则后续的渲染操作会影响到我们的 frame buffer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值