FBO Render to texture - black texture

331 views Asked by At

I try to use rendered texture (via FBO) to texture with it a cube. Unfortunately, I cannot do it. Texture is completely black, but when I try do it anotherwise with copy-pasted from one site function (drawObjects()) it renders quite good resized texture. I cannot spot the difference between my drawing code (Model3D::draw()) and copy-pasted function drawObjects().

I think that there is difference between texture formats, because when I use normal texture f.e. Model::loadTexture("data/sprites/floor4.png") texture is right rendered

#include "worldrender.h"

WorldRender::WorldRender() : world()
{
}

WorldRender::WorldRender(int argc, char **argv) : world(argc, argv)

{

}


void WorldRender::init()
{

    world::init();


    glGenFramebuffers(1, &frameBo); DEBUG;
    glBindFramebuffer(GL_FRAMEBUFFER, frameBo); DEBUG;


    glGenTextures(1, &renderedTexture); DEBUG;
    glBindTexture(GL_TEXTURE_2D, renderedTexture); DEBUG;

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIN_WIDTH, WIN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); DEBUG;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); DEBUG;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); DEBUG;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); DEBUG;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); DEBUG;


    glGenRenderbuffers(1, &depthBo); DEBUG;
    glBindRenderbuffer(GL_RENDERBUFFER, depthBo); DEBUG;
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WIN_WIDTH, WIN_HEIGHT); DEBUG;
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBo); DEBUG;

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0); DEBUG;
    GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; DEBUG;
    glDrawBuffers(1, DrawBuffers); DEBUG;

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        throw std::string("Frame buffer setup not complete");
    }

    obj *o = new obj("data/models/cube.obj");
    o->load();
    poster = new Model3D(o, "cube");
    poster->setPosition(glm::vec3(-0.5, -0.5, -0.5));

    s2 = s;
    poster->s = &s2;
    std::cerr << "Rendered texture (FBO): " << renderedTexture << std::endl;
    poster->replaceTexture(renderedTexture); // Uncomment this normal
    poster->init();


}

void WorldRender::postRenderFrame()
{

}

void WorldRender::destroy()
{
    world::destroy();

}

int WorldRender::exec(GLFWwindow *window) {
    this->window = window;
    init();
    glfwInit();
    ilInit();

    if (!window) {
        throw std::string("cannot create window");

    }


    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
    do {
        glBindFramebuffer(GL_FRAMEBUFFER, frameBo); DEBUG;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        renderFrame();
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        poster->draw(&s2);


        glfwSwapBuffers(window);
        glfwPollEvents();


    } while (glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
             glfwWindowShouldClose(window) == 0);



    glfwTerminate();

    return 0;

}

void WorldRender::preRenderFrame() {
    glBindFramebuffer(GL_FRAMEBUFFER, frameBo);
}

Model3D draw:

#include "model3d.h"

Model3D::Model3D() : Model()
{
}

Model3D::Model3D(obj *o,
                 std::string name,
                 std::string vShader,
                 std::string fShader)
        : Model(o,
                name,
                o->materials.at(o->objects.at(name).materialName),
                vShader,
                fShader) {

    vertices = &o->objects.at(name).vertices;
    uvs = &o->objects.at(name).uvs;
    normals = &o->objects.at(name).normals;
    indices = &o->objects.at(name).indices;
    m = o->materials.at(o->objects.at(name).materialName);

    std::cerr << "Material name: " << m.name << std::endl;
    std::cerr << "Materi kd path: " << m.mapKdPath << std::endl;
    std::cerr << "Texture path " << texturePath << std::endl;
    this->texturePath = texturePath;
    this->vertices = vertices;
    this->uvs = uvs;
    this->normals = normals;
    this->indices = indices;

    vao = initVao();
}


void Model3D::draw(scene *s) {
    DEBUG;
    double start = glfwGetTime();
    glm::mat4 translation = glm::translate(glm::mat4(1.0f),this->position);
    glm::mat4 rotation = glm::rotate(glm::mat4(1.0f),this->rotation[0], glm::vec3(1.0f, 0.0f, 0.0f));
    rotation = glm::rotate(rotation, this->rotation[1], glm::vec3(0, 1, 0));
    rotation = glm::rotate(rotation, this->rotation[2], glm::vec3(0, 0, 1));
    glm::mat4 scalation = glm::scale(glm::mat4(1.0f),scale);
    M = translation * rotation * scalation;

    glUseProgram(programID);
    DEBUG;

    glBindVertexArray(vao);
    DEBUG;
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);
    /**
    glEnableVertexAttribArray(4);
    glEnableVertexAttribArray(5);
    **/
    DEBUG;

    glBindBuffer(GL_ARRAY_BUFFER, vertexBo);
    glVertexAttribPointer(
            0, // attribute 0. Brak uzasadnienia
            3, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_FLOAT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    DEBUG;

    glBindBuffer(GL_ARRAY_BUFFER, uvBo);
    glVertexAttribPointer(
            1, // attribute 1. Brak uzasadnienia
            2, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_FLOAT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    glBindBuffer(GL_ARRAY_BUFFER, normalBo);
    glVertexAttribPointer(
            2, // attribute 0. Brak uzasadnienia
            3, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_FLOAT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    DEBUG;

    /**

    glBindBuffer(GL_ARRAY_BUFFER, tangentBo);
    glVertexAttribPointer(
            4, // attribute 0. Brak uzasadnienia
            3, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_FLOAT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    glBindBuffer(GL_ARRAY_BUFFER, bitangentBo);
    glVertexAttribPointer(
            5, // attribute 0. Brak uzasadnienia
            3, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_FLOAT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    **/

    preRender(s);
    DEBUG;

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBo);
    glVertexAttribPointer(
            3, // attribute 0. Brak uzasadnienia
            1, // uważaj, tu z ilu komponentów składa się atrybut vertexu
               // może być 1,2,3,4
            GL_UNSIGNED_INT, // type
            GL_FALSE, // znormalizowane
            0,        // stride
            (void*)0  // array buffer offset
    );

    DEBUG;

    glDrawElements(GL_TRIANGLES,
                   indices->size(),
                   GL_UNSIGNED_INT,
                   (void *)0);
    glBindVertexArray(0);

    DEBUG;

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
    DEBUG;
    /**
    glDisableVertexAttribArray(4);
    glDisableVertexAttribArray(5);
    **/

    postRender(s);
    DEBUG;
    double end = glfwGetTime();
    double diff = end-start;
    static double last = glfwGetTime();
    static std::list<float> times;
    static float sum = 0.0;

    times.push_front(diff);
    sum += diff;

    if (times.size() >= 20.0) {
        float lastDiff = times.back();
        times.pop_back();
        sum -= lastDiff;
    }

    float avg = sum / (float)times.size();
    float fps = 1.0 / avg;

    if (end - last >= 1.0) {
        last = end;

        fprintf(stderr, "Model3D %s draw FPS: %.2f, time: %.2fms\n",
                name.c_str(),
                fps,
                1000.0 * avg);
    }
    DEBUG;
}

void Model3D::preRender(scene *s) {
    // pobiermy id uchwytu dla danych
    if (s->lightPosition.size() != MAX_LIGHT_SOURCES) {
        throw std::string("Too low light sources in buffer");
    }

    GLuint matrixId = glGetUniformLocation(programID, "MVP");
    GLuint matrixId3 = glGetUniformLocation(programID, "MVP3");
    GLuint modelId = glGetUniformLocation(programID, "M");
    GLuint viewId = glGetUniformLocation(programID, "V");

    // GLuint texId2 = glGetUniformLocation(programID, "normalMap");
    glm::mat4 MVP = s->projection * s->view * M;
    glm::mat3 MVP3(MVP);

    // wysyłamy przekształcenie do aktualnie powiązanego shadera
    glUniformMatrix4fv(matrixId, 1, GL_FALSE, &MVP[0][0]);
    DEBUG;
    glUniformMatrix3fv(matrixId3, 1, GL_FALSE, &MVP3[0][0]);
    DEBUG;
    glUniformMatrix4fv(modelId, 1, GL_FALSE, &M[0][0]);
    DEBUG;
    glUniformMatrix4fv(viewId, 1, GL_FALSE, &s->view[0][0]);
    DEBUG;

    glActiveTexture(GL_TEXTURE0);
    DEBUG;
    glBindTexture(GL_TEXTURE_2D, textureID);

    updateTextureFilter();
    DEBUG;


}

void Model3D::postRender(scene *s) {

}

void Model3D::init() {

    Model::init();
    glUseProgram(programID);

    GLuint lightPosId = glGetUniformLocation(programID, "light_pos_world");

    GLuint texId1 = glGetUniformLocation(programID, "sampler");
    GLuint kAId = glGetUniformLocation(programID, "kA");
    GLuint kDId = glGetUniformLocation(programID, "kD");
    GLuint kSId = glGetUniformLocation(programID, "kS");
    GLuint kMaxDegrees = glGetUniformLocation(programID, "max_degree");
    DEBUG;
    GLuint kLightDirectionGlo = glGetUniformLocation(programID,
            "light_direction_glo");
    DEBUG;
    GLuint kSpotlight = glGetUniformLocation(programID,
            "spotlight");
    DEBUG;
    GLuint kColors = glGetUniformLocation(programID,
            "colors");
    DEBUG;
    GLuint nrLightSourcesId = glGetUniformLocation(programID, "nrLightSources");
    DEBUG;
    GLuint  kLightPowerID = glGetUniformLocation(programID,
            "lightPower");

    glUniform3fv(lightPosId, MAX_LIGHT_SOURCES, &s->lightPosition[0][0]);
    // do lightPosition musi wejść 8 elementów
    DEBUG;

    glUniform3fv(kAId, 1, &m.Ka[0]);
    DEBUG;
    glUniform3fv(kDId, 1, &m.Kd[0]);
    DEBUG;
    glUniform3fv(kSId, 1, &m.Ks[0]);
    DEBUG;
    glUniform1i(nrLightSourcesId, s->nrOfLights);
    DEBUG;

    glUniform1fv(kMaxDegrees, MAX_LIGHT_SOURCES, &s->max_degree[0]);
    DEBUG;
    glUniform3fv(kLightDirectionGlo, MAX_LIGHT_SOURCES,
            &s->lightDirection[0][0]);
    DEBUG;

    glUniform1iv(kSpotlight, MAX_LIGHT_SOURCES, &s->spotlight[0]);
    DEBUG;
    glUniform3fv(kColors, MAX_LIGHT_SOURCES, &s->colors[0][0]);
    DEBUG;
    glUniform1fv(kLightPowerID, MAX_LIGHT_SOURCES, &s->lightPower[0]);
    DEBUG;

    glActiveTexture(GL_TEXTURE0);
    DEBUG;
    glBindTexture(GL_TEXTURE_2D, textureID);
    DEBUG;
    texId1 = glGetUniformLocation(programID, "sampler");
    DEBUG;
    glUniform1i(texId1, 0);
    DEBUG;


}

void Model3D::destroy() {
    Model::destroy();
}

Model3D &Model3D::operator=(const Model3D &m) {
    Model::operator =(m);


    return *this;
}

Model3D::~Model3D() {
    destroy();
}

void Model3D::replaceTexture(GLuint texID) {
    this->textureID = texID;
    init();
}

I would like to ask, what could I do wrong?

2

There are 2 answers

0
tpsa On

The problem was not in the format, nor shaders only in texture filtering:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);

in Model::updateTextureFilter() where min_filter was GL_NEAREST_MIPMAP_NEAREST.

Why it has made such a drastic difference, I do not know.

0
L. Swifter On

There are two ways to solve this question:

  1. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  2. glGenerateMipmap(GL_TEXTURE_2D);

Either of these could solve the problem, but I don't know why those work.