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?
The problem was not in the format, nor shaders only in texture filtering:
in Model::updateTextureFilter() where min_filter was GL_NEAREST_MIPMAP_NEAREST.
Why it has made such a drastic difference, I do not know.