2014-03-06 38 views
2

我一直在努力学习最新的现代OpenGL/GLSL,这让我接触到了FBO的主题,并且遇到了一个神秘的问题。GLSL/OpenGL FBO不会解除绑定

在我的程序中,我初始化一个FBO,然后取消绑定它。一切工作到目前为止。然后绑定FBO,并将其场景呈现给它。当我运行这个程序时,我得到了一个空白屏幕,但这很正常 - 我没有渲染输出。但是,当我试图做到这一点,或尝试渲染任何东西时,我仍然会看到黑屏。只有在主循环期间不绑定FBO时,我才能使其工作。 我有使用LWJGL在Java中工作的FBO,这是我第二次尝试使用SDL呈现C++中的FBO,并且这两次都遇到了相同的错误。

它不是什么:

  • 质地 - 我已经尝试过使用FBO
  • 着色器后绘制其他纹理 - 我试过这个
  • 我的其他着色我使用包装类 - 它们在使用其他系统时都被证明可以工作。

此外,glChackFramebufferStatus(GL_FRAMEBUFFER)返回GL_FRAMEBUFFER_COMPLETE和glGetError()返回0 另外,据我所知,有几件事情我没有做这将是明智的(例如深度缓冲区),即不要影响这个bug。我会在稍后填写。

下面的代码: Main.cpp的:

#include <iostream> 
#include "GLee.h" 
#define GLM_FORCE_RADIANS 
#include "matrices.h" //Replaces built-in matrices, functions behave the same as legacy OGL 
#include "functions.h" //Camera, works very well 
#include <SDL/SDL.h> 
#include <SDL/SDL_image.h> 


#include <SDL/SDL_opengl.h> 
#include <SDL/SDL_mouse.h> 

#include <math.h> 
#include <SDL/SDL_opengl.h> 
#include <vector> 
#include <string> 
#include <algorithm> 
#include <fstream> 
#include <cstdio> 
#include <cstdlib> 




#include <GL/gl.h> 
#include <GL/glu.h> 


//#include <SDL/SDL_video.h> 

using namespace std; 

unsigned int grass, crate, FBOTex; 
int ground, monkey; 
bool mousein = true; 
matrices pipeline; 
int frame; 

#include <GL/gl.h> 
#include <GL/glu.h> 
#include "TexLoader.h" //Loads textures - I've never had issues with this header 
#include "ModelLoader.h" //Loads models (OBJ), again, works like a treat 
#include "shader.h" //Includes the shader class, which has been proven to work 
#include "Material.h" //Used in lighting calculations 

texProperties linear = texProperties(GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, 16); 
texProperties pixellated = texProperties(GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, 16); //Properties for textures loaded by the texture loader. 

shader* mainShader; 
shader* postProcess; //The FBO shader 
material simpleMaterial = material(0.2, 0.2, 0.2, 0.6, 0.6, 0.6, 0.1,0.1,0.1, 1000), 
littleShine = material(0.2, 0.2, 0.2, 0.6, 0.6, 0.6, 0.1,0.1,0.1, 5), 
monkeyMtl = material(0.2, 0.2, 0.2, 0.6, 0.6, 0.6, 0.3,0.3,0.3, 50); 
//monkeyMtl = material(0.2, 0.2, 0.2, 0.6, 0.6, 0.6, 1,1,1, 5); 

SDL_Surface* loadTextureData(const char* fileName){ //For creating icons 
    SDL_Surface* tex; 
    if((tex = IMG_Load(fileName))){ 
     cout<<"Texture Found! Tex: "<<fileName<<endl; 
    } 
    return tex; 
} 

unsigned int createTexture(int w, int h, bool isDepth){ //Create texture for FBO 
    unsigned int textureID; 
    glGenTextures(1, &textureID); 
    glBindTexture(GL_TEXTURE_2D, textureID); 
    glTexImage2D(GL_TEXTURE_2D, 0, isDepth?GL_DEPTH_COMPONENT:GL_RGBA8, w, h, 0, isDepth?GL_DEPTH_COMPONENT:GL_RGBA, GL_FLOAT, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    int i; 
    i = glGetError(); 
    if(i != 0){ 
     cout<<"Texture creation error! Error code: "<<i<<endl; 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 
    return textureID; 
} 

unsigned int fbo; //The FBO ID 
unsigned int renderTexture; //The ID of the output texture for the FBO 

void init(){ 
    //glEnable(GL_CULL_FACE); 
    //glCullFace(GL_BACK); 
    const unsigned char* text = glGetString(GL_VERSION); //OpenGL 4 
    cout<<"GL version: "<<text<<endl; 
    SDL_WM_GrabInput(SDL_GRAB_ON); 
    glEnable(GL_MULTISAMPLE); 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_TEXTURE_2D); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); 
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); 
    SDL_WM_SetCaption("OGL!", "OGL!!"); 
    //SDL_WM_IconifyWindow(); 
    SDL_Surface* icon = loadTextureData("Logo.png"); 
    SDL_WM_SetIcon(icon, NULL); 
    glClearColor(0.0, 0.0, 0.0, 1); 
    pipeline.matrixMode(PROJECTION_MATRIX); 
    pipeline.loadIdentity(); 

    pipeline.perspective(45, 1280.0/720.0, 0.1, 5000.0); //Similar to legacy OGL 
    pipeline.matrixMode(MODEL_MATRIX); 

    SDL_FreeSurface(icon); 

    mainShader = new shader("vertex.vert", "fragment.frag"); //These shader files   load+compile fine 
    postProcess = new shader("PostProcess.vert", "PostProcess.frag"); 
    grass = getTexture("Textures/Grass.png", linear); 
    crate = getTexture("Textures/Crate.png", linear); 
    ground = loadModel("Models/Plane.obj"); 
    monkey = loadModel("Models/Monkey.obj"); 
    float amb[3] {0.2, 0.2, 0.2}; 
    float diff[3] {0.6, 0.6, 0.6}; 
    float spec[3] {1, 1, 1}; 

    //////////FBO Creation/////////// 
    glGenFramebuffers(1, &fbo); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);//This bind function works 
    renderTexture = createTexture(1920, 1080, false); 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0); 

    int i = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    if(i != GL_FRAMEBUFFER_COMPLETE){//I get no errors here... 
     cout<<"FBO is not complete!"<<endl; 
    } 
    cout<<"glGetError() = "<<glGetError()<<endl; //Prints 0 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); //This unbind works perfectly 
} 

void display(){ //The drawing part of the main loop 
    cout<<"FBO Number: "<<fbo<<endl; //Returns 1, as it should 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
    mainShader->bindShader(); 
    mainShader->setUniformFloat3("lspecular", 1,1,1); //Lighting stuff... 
    mainShader->setUniformFloat3("lambient", 0.2,0.2,0.2); 
    mainShader->setUniformFloat3("ldiffuse", 0.6,0.6,0.6); 

    mainShader->setUniformFloat3("lightPos", 0,500,0); 
    mainShader->setUniformSampler("texture", 0); 
    mainShader->setUniformFloat("constantAttenuation", 0.0); 
    mainShader->setUniformFloat("linearAttenuation", 0.0); 
    mainShader->setUniformFloat("quadraticAttenuation", 0.000002); 
    littleShine.addToShader(*mainShader); //Sets material for lighting 
    pipeline.matrixMode(PROJECTION_MATRIX); 
    pipeline.loadIdentity(); 
    pipeline.perspective(45, 1280.0/720.0, 0.1, 5000.0); //3D projection 
    pipeline.matrixMode(VIEW_MATRIX); 
    pipeline.loadIdentity(); 
    control(0.2, 0.2, mousein, pipeline); //Controls camera 
    updateCamera(pipeline); //Updates matrices 
    pipeline.updateMatrices(mainShader->getHandle()); //Updates shader matrices 
    glBindTexture(GL_TEXTURE_2D, grass); 
    pipeline.matrixMode(MODEL_MATRIX); 
    //pipeline.loadIdentity(); 

    glCallList(ground); 

    pipeline.translate(0, 1, -5); 
    pipeline.rotatef(frame, 0, 1, 0); 
    pipeline.updateMatrices(mainShader->getHandle()); 
    monkeyMtl.addToShader(*mainShader); 
    glBindTexture(GL_TEXTURE_2D, crate); 
    glCallList(monkey); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); ///////DOESN'T UNBIND!! Still get black screen 
    //glClear(GL_COLOR_BUFFER_BIT); 
    pipeline.matrixMode(MODEL_MATRIX); 
    pipeline.loadIdentity(); 
    pipeline.matrixMode(VIEW_MATRIX); 
    pipeline.loadIdentity(); 
    //pipeline.translate(0, 0, -5); 
    pipeline.matrixMode(PROJECTION_MATRIX); 
    pipeline.loadIdentity(); 
    pipeline.ortho(1920, 0, 0, 1080, 1, -1);//Clear matrices, set orthographic view 
    //mainShader->unbindShader(); 
    postProcess->bindShader(); //Binds the post-processing shader 
    postProcess->setUniformSampler("texture", 0); //Texture sampler 
    pipeline.updateMatrices(postProcess->getHandle()); 
    glBindTexture(GL_TEXTURE_2D, renderTexture); //Bind the FBO's output as a texture 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); //Tried a second time to unbind FBO, to no avail... 
    glBegin(GL_QUADS); 

    glColor3f(1.0, 1.0, 1.0); //Makes no difference 
     glTexCoord2f(0,0);  /////Draw FBO texture to screen, fails 
     glVertex2f(0,0);        
     glTexCoord2f(1,0); 
     glVertex2f(1920,0); 
     glTexCoord2f(1,1); 
     glVertex2f(1920,1080); 
     glTexCoord2f(0,1); 
     glVertex2f(0,1080); 
    glEnd(); 

} 
void update(){ 
    frame++; 
} 

int main(int args, char* argv[]){ 
    SDL_Init(SDL_INIT_EVERYTHING); 
    IMG_Init(IMG_INIT_PNG); 
    SDL_Delay(150); 
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); 
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); 
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
    SDL_Surface* screen = SDL_SetVideoMode(1920, 1080, 32, SDL_SWSURFACE|SDL_OPENGL|SDL_FULLSCREEN); 

    bool running = true; 
    Uint32 start; 
    SDL_Event event; 
    init(); 
    while(running){ 
     start = SDL_GetTicks(); 
     while(SDL_PollEvent(&event)){ 
      switch(event.type){ 
      case SDL_QUIT: 
       running = false; 
      break; 
      case SDL_KEYDOWN: 
      switch(event.key.keysym.sym){ 
      default: 
       break; 
       case SDLK_ESCAPE: 
        running = false; 
       break; 
       case SDLK_p: 
        mousein = false; 
        SDL_ShowCursor(SDL_ENABLE); 
        SDL_WM_GrabInput(SDL_GRAB_OFF); 
        break; 
      } 
       break; 
      case SDL_KEYUP: 

       break; 
      case SDL_MOUSEBUTTONDOWN: 
       mousein = true; 
       SDL_ShowCursor(SDL_DISABLE); 
       SDL_WM_GrabInput(SDL_GRAB_ON); 
       break; 
      } 
     } 
     update(); 
     display(); 
     SDL_GL_SwapBuffers(); 
     if(1000/60 > (SDL_GetTicks() - start)){ 
      SDL_Delay(1000/60 - (SDL_GetTicks() - start)); 
     } 
    } 
    delete mainShader; 
    SDL_Quit(); 
    //cout << "Hello world!" << endl; 
    return 0; 
} 

PostProcess.vert:

#version 130 
varying vec2 texCoord; 
varying vec3 position; 
varying vec3 normal; 
//Matrices, passed in to shader 
uniform mat4 modelMatrix; 
uniform mat4 viewMatrix; 
uniform mat4 projectionMatrix; 
uniform mat4 modelViewMatrix; 
uniform mat4 modelViewProjectionMatrix; 
uniform mat3 normalMatrix; 


void main(){ 
    gl_Position = modelViewProjectionMatrix * gl_Vertex; 
    normal = normalMatrix * gl_Normal; 
    texCoord = gl_MultiTexCoord0.st; 
    position = vec3(modelViewMatrix * gl_Vertex); 
} 

PostProcess.frag:

#version 130 
uniform sampler2D texture; 
varying vec2 texCoord; 
varying vec3 position; 
varying vec3 normal; 

void main(){ 
    gl_FragColor = texture(texture, texCoord); //Draw the textur, also tried texture2D... 
    //gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //I've tried drawing white to the screen - it failed 
} 

我真的不知道发生了什么这里。我猜想这很简单,但我怎么错过了两次?

+0

您是否在绘图调用失败后检查错误? – user26347

+0

我从来没有想到这一点!我得到了1281(0x501)的错误 - 无效值。谢谢!我会看到我可以用这个做什么... – Superdavo

+0

是的,我仍然没有看到任何东西。你可以尝试移动错误检查或添加更多,看看是否缩小了。 – user26347

回答

1

我已经解决了!

出于某种原因,material.cpp文件搞得一团糟。出于某种原因,当我使用material.addToShader(着色器)函数时,它不会渲染,但是当我自己添加了制服时,或者将参数更改为指向着色器的指针时,它似乎工作得很好。 这个问题导致了1281错误。为什么这是我不知道的情况,但至少现在已经解决了!

0

当窗口framebuffer被绑定时,您不会调用glClear。试试:

glBindFramebuffer(GL_FRAMEBUFFER, 0); 

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
+0

这是有用的建议,但我试过了,仍然得到一个黑屏:( – Superdavo