0
votes

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();
}

Full code: https://bitbucket.org/tpsa/grafika-3d-laboratorium/src/4aa4edf09120e9f96694a1b811a051312ebb4bba/src/worldrender.cpp?at=render-to-texture-apply

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

1
What do you use to load the texture? Since your framebufffer is using RGBA you need to make sure you're loading your textures as RGBA and also make sure the texture has these channels in the first place. - Iggy
Any chance of simplifying this? I started reading, but aside from the pure amount of code, it seems to contain the same code multiple times. - Reto Koradi

1 Answers

0
votes

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.