Hello all,
I’m trying to load a bitmap file and create a texture to display on a 3D cube. I am using FreeImage to load the image and tinyobjloader to load the .obj file storing the cube data. When rendering no texture is shown and all faces of the cube are black.
Here is my code to generate the texture for the object:
GeoModel3D::GeoModel3D(std::string file_name)
{
std::string err = tinyobj::LoadObj(shapes, materials, (file_name+".obj").c_str());
std::cout<<err<<std::endl;
for(size_t i = 0;i<shapes.size();i++ )
{
tinyobj::mesh_t current_mesh = shapes[i].mesh;
if(current_mesh.material_ids[0]>=0) // no texture = -1 in material ids
{
tinyobj::material_t& material = materials[current_mesh.material_ids[0]];
std::string color_map = material.diffuse_texname;
if (!color_map.empty())
{
GLuint texture_id = loadTexture(color_map);
textures.insert(std::map<unsigned int,unsigned int>::value_type(current_mesh.material_ids[0],texture_id));
}
}
}
if(err.empty())
{
std::cout << "Name of object : " << file_name << std::endl;
std::cout << "# of shapes : " << shapes.size() << std::endl;
std::cout << "# of materials : " << materials.size() << std::endl;
}
}
GLuint GeoModel3D::loadTexture(std::string file_name)
{
GLuint texture_id;
FREE_IMAGE_FORMAT formato = FreeImage_GetFileType(file_name.c_str(),0);
if(formato == FIF_UNKNOWN)
{ std::cout<<"Unknown file format"<<std::endl; }
FIBITMAP* image = FreeImage_Load(formato, file_name.c_str());
if(!image )
{ std::cout<<"Could not load image"<<std::endl; }
FIBITMAP* temp = FreeImage_ConvertTo32Bits(image);
if(!image)
{ std::cout<<"Could not convert to 32-bit image"<<std::endl; }
FreeImage_Unload(image);
image = temp;
if(!image)
{
std::cout<<"Could not open "+file_name<<std::endl;
}
else
{
std::cout<<"Successfully opened "+file_name<<std::endl;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
FreeImage_GetWidth(image), FreeImage_GetHeight(image),
0, GL_RGB, GL_UNSIGNED_BYTE, image->data);
std::cout<<"Generated texture with handle: "<<texture_id<< std::endl;
return texture_id;
}
return -1;
}
And here is my code to render the cube and pass the texture to the shaders:
void GeoModel3D::render(cwc::glShader *shader, Camera camera)
{
GLuint vertexBuffer, normalBuffer, texCoordBuffer;
GLint vertex_index = 0; //store location of the "position" attribute in shaders
GLint normal_index = 1; //store location of the "normal" attribute in shaders
GLint sampler_index; //store location of the "diffuseTexture" attribute in the frag shader
GLint texture_coords_index = 2;
GLint model_index;
GLint view_index;
GLint projection_index;
glm::mat4 modelMatrix = camera.getModelMatrix();
glm::mat4 viewMatrix = camera.getViewMatrix();
glm::mat4 projectionMatrix = camera.getProjectionMatrix();
/*modelMatrix = glm::rotate(modelMatrix,1.0f,glm::vec3(0,0,-100));*/ // can be used to check back face
model_index = shader->GetUniformLocation( "model" );
glUniformMatrix4fv( model_index, 1, GL_FALSE, &modelMatrix[0][0] );
view_index = shader->GetUniformLocation( "view" );
glUniformMatrix4fv( view_index, 1, GL_FALSE, &viewMatrix[0][0] );
projection_index = shader->GetUniformLocation( "projection" );
glUniformMatrix4fv(projection_index,1,GL_FALSE,&projectionMatrix[0][0]);
//for all shapes in the obj file
for(size_t i = 0;i<shapes.size();i++ )
{
tinyobj::mesh_t current_mesh = shapes[i].mesh;
shader->BindAttribLocation(normal_index,"normal");
glGenBuffers(1,&normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(float)*current_mesh.normals.size(), ¤t_mesh.normals[0],GL_STATIC_DRAW);
glVertexAttribPointer(normal_index, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(normal_index);
shader->BindAttribLocation(vertex_index,"position");
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(float)*current_mesh.positions.size(), ¤t_mesh.positions[0], GL_STATIC_DRAW);
glVertexAttribPointer(vertex_index, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertex_index);
shader->BindAttribLocation(texture_coords_index,"texCoord");
glGenBuffers(1, &texCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER,texCoordBuffer);
glVertexAttribPointer(texture_coords_index, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBufferData(GL_ARRAY_BUFFER,sizeof(float)*current_mesh.texcoords.size(), ¤t_mesh.texcoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(texture_coords_index);
if(current_mesh.material_ids[0]>=0)
{
tinyobj::material_t& material = materials[current_mesh.material_ids[0]];
unsigned int texture_id = textures.at(current_mesh.material_ids[0]);
sampler_index = shader->GetUniformLocation("sampler");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glUniform1i(sampler_index, 0);
std::cout<<"Binding texture handle: " << texture_id <<" to the shader" <<std::endl;
}
glDrawElements(GL_TRIANGLES, shapes[i].mesh.indices.size(), GL_UNSIGNED_INT, ¤t_mesh.indices[0] );
glDisableVertexAttribArray(vertex_index);
glDisableVertexAttribArray(normal_index);
glDisableVertexAttribArray(texture_coords_index);
}
}
My vertex shader code is:
#version 140
in vec3 position;
in vec2 texCoord;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;
out vec2 texture_coord;
void main( void )
{
gl_Position = projection * view * model * vec4(position, 1.0);
texture_coord = texCoord;
}
And fragment shader code is:
#version 140
in vec2 texture_coord;
uniform sampler2D sampler;
out vec3 color;
void main()
{
color = texture(sampler, texture_coord).rgb;
}
OpenGL vendor: Intel.
OpenGL renderer: Intel® HD Graphics 3000.
OpenGL version: 3.1.0
I can set a solid colour in the shader and the image used is a 24-bit 256x256 bitmap. I have been looking through various similar topics for a few days now and I feel like I’m going around in circles so any help would be really appreciated.