PDA

View Full Version : black texture



mustardpower
11-16-2014, 05:22 AM
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(), &current_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(), &current_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(), &current_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, &current_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(R) 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.

DragonForce99
11-16-2014, 10:19 AM
1- if you are using glsl torender your texture you don't need glEnable(GL_TEXTURE_2D);

2-
FreeImage_GetWidth(image), FreeImage_GetHeight(image),
0, GL_RGB, GL_UNSIGNED_BYTE, image->data);

try to use FreeImage_GetBits(pImage) instead image->data

3 - if you want to check if the problem is in loading texture try to create 2X2 texture read color or green

mustardpower
11-16-2014, 12:13 PM
With those changes (the second one made the difference) I now get a solid blue colour rather than black which is presumably better.

DragonForce99
11-17-2014, 04:27 AM
check the uv Texcoord

mustardpower
11-17-2014, 11:46 AM
current_mesh.texture_coords contains 48 values (a U and a V component for each of the 4 vertices on each of the 6 faces of the cube) with values in the range [0,1]. When I change my fragment shader to the following, I get a red and a green face and the other 4 faces are black.



#version 140

in vec2 texture_coord;

out vec3 color;

void main()
{
color = vec3(texture_coord,0.0);
}