c++ - GLSL/OpenGL FBO 不会解除绑定(bind)

标签 c++ opengl glsl sdl fbo

最近我一直在尝试学习现代 OpenGL/GLSL,这让我想到了 FBO 的主题,我遇到了一个神秘的问题。

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

它不是什么:

  • 纹理 - 在使用 FBO 后我已经尝试绘制其他纹理
  • 着色器 - 我已经在这上面尝试了我的其他着色器
  • 我使用的包装器类 - 它们都已被证明在使用其他系统时也能正常工作。

此外,glChackFramebufferStatus(GL_FRAMEBUFFER) 返回 GL_FRAMEBUFFER_COMPLETE,而 glGetError() 返回 0。 此外,我知道有一些我没有做的事情是明智的(例如深度缓冲区),不会影响这个错误。我稍后会填写这些内容。

代码如下: 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;
}

后处理.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);
}

后处理片段:

#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
}

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

最佳答案

我已经解决了!

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

关于c++ - GLSL/OpenGL FBO 不会解除绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22235860/

相关文章:

c++ - 通过使用深度缓冲区丢弃重叠像素来优化 OpenGL 2D 渲染?

c++ - 使用 hu 矩训练 SVM

c++ - 如何在 VS2010 Express 中独立发布/调试静态库?

c++ - OpenGL/GLUT 试图使水平杆以不同方式波动

c++ - 如何重用相同的顶点着色器来绘制不同的 gl_Position

c++ - g++ 同时链接静态库和非静态库

c++ - 关于 GLM 网格中的碰撞检测

c++ - glsl - 获取像素颜色 [像素着色器]

opengl - 如何将多个纹理传递给单个着色器?

c++ - 将值传递给 main(int, char**)