从纹理渲染到屏幕外纹理 (FBO)

Posted

技术标签:

【中文标题】从纹理渲染到屏幕外纹理 (FBO)【英文标题】:rendering from texture to offscreen texture ( FBO) 【发布时间】:2013-10-21 04:19:03 【问题描述】:

我正在尝试编写一个 GPGPU 程序,只需将纹理的内容复制到附加到 FBO 的输出纹理。但是,我看到输入纹理数据未正确加载/未正确绑定。我不明白出了什么问题。

这是我的代码:

void render()


  int i;
  float * result, *in;

  //allocating and filling data in the input texture

  result = (float * ) malloc(4*32*32*sizeof(float));
  in = (float *) malloc(4*32*32*sizeof(float));
  for(i=0;i<32*32*4; i++)
  
    in[i]=1.0f;
  


makeBuffers(); //makes the vertex and element buffers
makeTexture(in);  //makes the input textures
makeShaders();    //makes the vertex n pixel shaders
makeProgram();   //makes the program

glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);

glBindBuffer(GL_ARRAY_BUFFER, res.vertexBuffer);
glVertexAttribPointer(res.position, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);
glEnableVertexAttribArray(res.position);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, res.elementBuffer);
res.texture= glGetUniformLocation(res.shaderProgram, "intexture");

/* 绑定纹理 */ makefbo(); // 制作离屏帧缓冲对象

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, res.texture);
glUniform1i(res.texture, 0);


glDrawElements(GL_TRIANGLE_STRIP,4, GL_UNSIGNED_SHORT, (void*)0);

//    glFlush();   // i think drawing would be enough now. 

glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);   //reading back data from the framebuffer
glReadPixels(0, 0, 32, 32,GL_RGBA,GL_FLOAT,result);

printf(" float values \n");
for(i=0; i< 32*4 ; i++)
  printf(" %f   ", result[i]);
printf(" \n");

这是我的 maketexture() 函数

 glGenTextures (1, &res.texture);
glBindTexture(GL_TEXTURE_2D,res.texture);
// set texture parameters
glTexParameteri(GL_TEXTURE_2D,
                GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
                GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
                GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,
                GL_TEXTURE_WRAP_T, GL_CLAMP);
// define texture with floating point format
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,
             texSize,texSize,0,GL_RGBA,GL_FLOAT,0);

// transfer data to texture
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,texSize,texSize,
                GL_RGBA,GL_FLOAT,data);

这是我的 framebufferoject 准备和输出纹理绑定:

glGenFramebuffers(1, &res.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, res.fbo);
glViewport(0, 0, 32, 32);

glGenTextures(1, &res.tex);
glBindTexture(GL_TEXTURE_2D, res.fbo);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 
         32, 32, 0, GL_RGBA, GL_FLOAT, 0);
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, 
                      GL_COLOR_ATTACHMENT0, 
                      GL_TEXTURE_2D, res.tex, 0);

数据似乎没有被正确读取。我尝试将输入纹理附加到帧缓冲区对象,并尝试立即读回纹理数据,然后数据显示正常。但是当我尝试渲染到屏幕外纹理时,它不会给出正确的输出。它在像素着色器执行结束时只给出一堆零。

像素着色器获取输入纹理并将数据复制到输出纹理中: outColor = texture2D (intexture, texcoord );

有人能看出这有什么问题吗?

【问题讨论】:

请不要说每次渲染一帧都是自己创建纹理、fbo、vao等。 我不是每次都渲染,这是一次性操作。我只需要处理一次数据。 【参考方案1】:

您的代码缺少很多上下文,但我的印象是您将所有内容完全绑定一次,然后就这样离开了。这不是它的用途,而且很可能不起作用。

基本要点是,如果纹理用作 FBO 渲染目标,则它不能用作采样源。因此,您必须根据需要取消绑定纹理/FBO,这样事情就不会踩到彼此的脚趾,或者您正在加载仅进行禁止纹理访问的着色器。恕我直言,取消绑定是更简单的选项(但是在 OpenGL-4.4 中发布了无绑定纹理扩展,这可能成为 4.5 的核心)。

【讨论】:

是的,我只绑定一次,因为我只需要一次性处理数据。我不会再渲染一次了。 关于解除绑定:我正在尝试将输入纹理原样复制到输出纹理,这是否意味着输入和输出纹理应该同时绑定到渲染目标? @saipallavi:不,这意味着完全不这样做。使用glFramebufferTexture 将输出纹理作为颜色附件绑定到FBO。必须通过将输入纹理与glBindTexture 绑定到纹理单元来选择输入纹理作为采样源。

以上是关于从纹理渲染到屏幕外纹理 (FBO)的主要内容,如果未能解决你的问题,请参考以下文章

为啥渲染到 FBO 会导致纹理变暗?

渲染到窗口帧缓冲区和 FBO 以保存全尺寸纹理图像

GLSL:无法从 FBO 读取纹理并使用片段着色器渲染到另一个 FBO

FBO:渲染到纹理,绘制渲染纹理时纹理映射错误

使用 FBO 和着色器 OpenGL 渲染到纹理

渲染到屏幕和 FBO 给出不同的结果