将屏幕外帧缓冲纹理渲染为主帧缓冲
render offscreen framebuffer texture to main framebuffer
我正在尝试使用一个帧缓冲对象,我无法控制它的设置方式。所以我正在创建一个具有深度的屏幕外fbo来绘制我的纹理。然后将其绘制到主帧缓冲区。我可以使用 OpenGL 分析器从资源中看到纹理,但我似乎无法让它绘制到主帧缓冲区。
这是我的代码
GLsizei glSizeWidthEquiv = width;
GLsizei glSizeHeightEquiv = height;
GLint originalFramebuffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFramebuffer);
if(fbo == 0){
glGenFramebuffers(1, &fbo);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//Creating texture for framebuffer
if(texColorBuffer == 0){
glGenTextures(1, &texColorBuffer);
}
glBindTexture([outTex target], texColorBuffer);
//Having it as null means the texture's data will be created dynamically
//Using RGBA since the alpha layer is going to be needed
glTexImage2D([outTex target], 0, GL_RGBA_FLOAT16_APPLE, glSizeWidthEquiv, glSizeHeightEquiv, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri([outTex target], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri([outTex target], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Attach texture to framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, [outTex target], texColorBuffer, 0);
//Creating render buffer
if(renderBuffer == 0){
glGenRenderbuffers(1, &renderBuffer);
}
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, glSizeWidthEquiv, glSizeHeightEquiv);
//Binding the renderbuffer to the framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
//Check framebuffer
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
NSLog(@"Framebuffer incomplete noobn");
}else{
NSLog(@"Framebuffer COMPLETE!n");
}
//Start to use the frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, glSizeWidthEquiv, glSizeHeightEquiv);
//cleaning texture: cleaning code here
//initating glTex0
glActiveTexture(GL_TEXTURE0);
//setting up texture stuff
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glDisable(GL_CULL_FACE);
glColor3f(1,0,0);
glBegin(GL_QUADS);
//box 1 in front
glVertex3f(0, 0, 0);
glVertex3f(500, 0, 0);
glVertex3f(500, 500, 0);
glVertex3f(0, 500, 0);
//box 2 at the back
glColor3f(0, 1, 0);
glVertex3f(-250, -250, 50);
glVertex3f(250, -250, 50);
glVertex3f(250, 250, 50);
glVertex3f(-250, 250, 50);
glEnd();
glFogCoordf(9);
//End of framebuffer usage
glBindFramebuffer(GL_FRAMEBUFFER, originalFramebuffer);
glViewport(0, 0, (GLsizei)[outTex width], (GLsizei)[outTex height]);
[self glGetError];
glActiveTexture(GL_TEXTURE0);
glBindTexture([outTex target], texColorBuffer);
glCopyTexSubImage2D([outTex target], 0, 0, 0, 0, 0, glSizeWidthEquiv, glSizeHeightEquiv);
glFlush();
程序的这一部分位于渲染部分,我在初始化时将fbo,renderBuffer和texColorBuffer设置为0,以防止它生成新的缓冲区。
所以本质上我正在创建缓冲区,直到它完成,然后重新绑定我创建的 fbo 来绘制我的形状。切换回原始 fbo 并尝试绘制它。
这里使用的[outTex目标]是GL_TEXTURE_RECTANGLE_ARB。
这是我在OpenGL分析器的纹理部分中的内容:http://img.photobucket.com/albums/v442/ardo/ScreenShot2013-10-27at112742PM.png
@GMasucci
我不完全确定这是否是创建 sscce 的正确方法,但这里有一个易于复制粘贴的代码,包括库、GLUT 和 OpenGL。这里使用的代码是从 www.videotutorialsrock.com 照明课程中捎带而来的,因此我有一个类似的环境。
#include <iostream>
#include <stdlib.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
GLuint fbo,texColorBuffer,renderBuffer;
float camMatrix [4][4];
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -8.0f);
if(fbo == 0){
glGenFramebuffers(1, &fbo);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
if(texColorBuffer == 0){
glGenTextures(1, &texColorBuffer);
}
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 400, 400, 0, GL_RGBA, 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);
if(renderBuffer == 0){
glGenRenderbuffers(1, &renderBuffer);
}
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 400, 400);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
printf("Error in framebuffer completeness n");
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, 400, 400);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBegin(GL_QUADS);
glColor3f(1,0,0);
glVertex3f(0, 0, 0);
glVertex3f(200, 0, 0);
glVertex3f(200, 200, 0);
glVertex3f(0, 200, 0);
glColor3f(0, 1, 0);
glVertex3f(-100, -100, -1);
glVertex3f(100, -100, -1);
glVertex3f(100, 100, -1);
glVertex3f(-100, 100, -1);
glEnd();
glFogCoordf(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, (GLsizei)400, (GLsizei)400);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 400, 400);
glutSwapBuffers();
}
void update(int value) {
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
//set fbo,texBuffer and renderbuffer to 0
fbo = 0;
texColorBuffer = 0;
renderBuffer = 0;
//Create the window
glutCreateWindow("Lighting - videotutorialsrock.com");
initRendering();
//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0); //Add a timer
glutMainLoop();
return 0;
}
以前从未使用过glCopyTexSubImage2D
,这是我对 opengl 手册页的最佳解释。
与 http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml 相比
块引用 glCopyTexSubImage2D 将二维纹理图像、立方体贴图纹理图像的矩形部分或一维数组纹理的多个切片的线性部分替换为当前GL_READ_BUFFER中的像素(而不是像 glTexSubImage2D 那样来自主内存)。
听起来您正在用originalFramebuffer
替换texColorBuffer
中的内容.
我将帧缓冲对象绘制到屏幕的方式是使用带纹理的全屏四边形,如下所示:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glPushMatrix();
GLfloat identity[4][4];
for (int i=0; i<4; ++i){
for (int j=0; j<4; ++j){
identity[i][j] = 0;
}
}
identity[0][0] = identity[1][1] = identity[2][2] = identity[3][3] = 1;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(identity);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(identity);
glActiveTexture(GL_TEXTURE0);
glBindTexture([outTex target], texColorBuffer);
glBegin(GL_QUADS);
glVertex2f(-1,-1);
glTexCoord2f(0, 0);
glVertex2f( 1,-1);
glTexCoord2f(1, 0);
glVertex2f( 1, 1);
glTexCoord2f(1, 1);
glVertex2f(-1, 1);
glTexCoord2f(0, 1);
glEnd();
glPopMatrix();
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- SFML纹理像播放器
- OpenGL大的3D纹理(>2GB)非常慢
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 如何使用原子指针执行双缓冲
- 着色器纹理值与创建纹理时写入的值不同
- OpenGL将纹理四边形渲染为(0,0)
- 宽度为奇数的16位纹理为片状
- 消费者和生产者问题的双重缓冲
- 使用 CUDA 和纹理进行图像减法
- 在不使用统一的情况下将纹理传递给 GLSL 着色器?
- 将使用太多的纹理插值器 - 带旋转的着色器
- dx11 渲染到纹理仅显示透明颜色
- OpenGL 4.3 错误地将第 4 个纹理坐标映射到与第 3 个纹理坐标相同的位置
- 帧缓冲纹理变为白色(片段着色器不会影响它)
- 将屏幕外帧缓冲纹理渲染为主帧缓冲
- 将RGBA32F纹理与帧缓冲抛出INVALID_ENUM错误一起使用
- OpenGL:从许多帧缓冲纹理中读取空间像素数据的有效方法
- 我如何缓冲模型矩阵数据到纹理使用OpenGL ES2, GLSL, c++
- OpenGL帧缓冲深度纹理不起作用