as part of migrating to OGL 3.3 (from 2.1) I'm rewriting my code so that I throw out all the immediate mode stuff and use shaders etc. however I got stuck at texturing. I can successfully load the shader (link etc.), load the texture (a png file), load the mesh with the texture coordinates, I can pass the values to the video card through vbos, and also I can pass the uniforms and get them through OGL glGetUniformLocation() however when I'm rendering nothing appears on screen (except untextured stuff).
so here's my vertex shader:
/*
* texture.vs
*
*/
#version 330
//something is not right...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, floor.texture);
glUniform1i(glGetUniformLocation(texturing_shader.shader_program, texturing_shader.resources[2].name.c_str()), 0);
One good thing to check if you're not getting anything is to just draw your meshes with the texcoord as the color, bypassing the texture sample. This guarantees that your mesh is there and the texcoords are getting loaded correctly.
If that looks correct but your texture isn't working, then you have to look at the texture itself as a source of error.
How are you sure the texture is being loaded properly? Are you enabling/disabling mipmaps properly with glTexParameter?
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
I'm sure because with OGL 2.1 functions it worked.
I haven't messed with mipmaps yet, but when I enable them the result is the same.
(I took the mipmap generator from mesa and put it into a class, so that I'm not using the deprecated functions and I still have mipmapping)
Make sure you disable mipmap filtering if you don't generate them. (You can generate mipmaps with non-deprecated function with glGenerateMipmap).
Anyway, its difficult to say if there's something wrong with your rendering code, would need to see vbo and texture initialization to be able to spot problems there.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
you're right it is...
however I can't find the problem...
here's the vbo init:
void render::fill_vbos(mesh& the_mesh)
{
typedef GLfloat float_3[3]; //so that we have one type with 3 components
typedef GLfloat float_2[2];
float_3* tmp_vertices; //temporary data that will be updated to the VGA
float_3* tmp_normals;
GLuint* tmp_faces;
float_2* tmp_tex_coords;
tmp_vertices = new float_3[the_mesh.faces.size() * 3]; //we allocate space for every face we have
tmp_normals = new float_3[the_mesh.faces.size() * 3];
tmp_faces = new uint[the_mesh.faces.size() * 3];
tmp_tex_coords = new float_2[the_mesh.faces.size() * 3];
the_mesh.numindexes = 0;
int num_index = -1; //this is our face counter
for (int c = 0; c < the_mesh.faces.size(); c++) //for every face
{
for (int i = 0; i < 3; i++) //for every vertex in each face
{
num_index++; //increase the face counter so that it points to the actual face (1st is 0)
for (int j = 0; j < 3; j++) //for every component in each vertex
{
tmp_vertices[num_index][j] = the_mesh.vertices[the_mesh.faces[c][i * 3] - 1][j]; //copy the associated vertex & normal data
tmp_normals[num_index][j] = the_mesh.normals[the_mesh.faces[c][i * 3 + 2] - 1][j];
}
if (the_mesh.tex_coords.size() > 0) //if we have tex coords, otherwise we'd have random values, and probably tex_coords doesn't have that much elements or it'd point to negative values...
{
tmp_tex_coords[num_index][0] = the_mesh.tex_coords[the_mesh.faces[c][i * 3 + 1] - 1][0]; //copy tex coords if we have some
tmp_tex_coords[num_index][1] = the_mesh.tex_coords[the_mesh.faces[c][i * 3 + 1] - 1][1];
}
tmp_faces[c * 3 + i] = num_index; //copy the index of the actual face (it'll be from 0 to the_mesh.faces.size() - 1, incremented always by 1 like 0, 1, 2, 3, ... (if I find out how to draw stuff without them, then they're useless, I mean they're in order the video card should just loop through them))
}
}
the_mesh.numindexes = num_index + 1; //assing the actual number of faces we'll upload to the VGA
glGenBuffers(4, the_mesh.vbos); //generate the VBOs (vertex, normal, tex coord, indices)
// Copy data to video memory
// Vertex data
glBindBuffer(GL_ARRAY_BUFFER, the_mesh.vbos[the_mesh.VERTEX_VBO]); //pass data to the VGA
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*the_mesh.numindexes*3, tmp_vertices, GL_STATIC_DRAW);
// Normal data
glBindBuffer(GL_ARRAY_BUFFER, the_mesh.vbos[the_mesh.NORMAL_VBO]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*the_mesh.numindexes*3, tmp_normals, GL_STATIC_DRAW);
void image_loader::load_image(const char* filename) //loading a image file with freeimage
{
std::cout << "-Loading: " << filename << "\n";
// Get the image file type from FreeImage.
FREE_IMAGE_FORMAT file_format = FreeImage_GetFileType(filename, 0); //get the file format
// Actually load the image file.
FIBITMAP *dib = FreeImage_Load(file_format, filename, 0); //load the file based on the file format & the filename
// Now, there is no guarantee that the image file
// loaded will be GL_RGBA, so we force FreeImage to
// convert the image to GL_RGBA.
dib = FreeImage_ConvertTo32Bits(dib); //we only want RGBA textures, so that our life will be easier
if ( dib != NULL ) //if it did load the texture
{
// This is important to note, FreeImage loads textures in
// BGR format. Now we could just use the GL_BGR extension
// But, we will simply swap the B and R components ourselves.
// Firstly, allocate the new bit data doe the image.
BYTE* bits = new BYTE[FreeImage_GetWidth(dib) * FreeImage_GetHeight(dib) * 4]; //then allocate space for each pixel
// get a pointer to FreeImage's data.
BYTE* pixels = FreeImage_GetBits(dib);
// Iterate through the pixels, copying the data
// from 'pixels' to 'bits' except in RGB format.
for (int pix = 0; pix < FreeImage_GetWidth(dib) * FreeImage_GetHeight(dib); pix++) //freeimage loads the images in a wierd color order, so I had to figure it out how to convert them to a proper color order (RGBA)
{
bits[pix * 4 + 0] = pixels[pix * 4 + 3]; //r = 3
bits[pix * 4 + 1] = pixels[pix * 4 + 0]; //g = 0
bits[pix * 4 + 2] = pixels[pix * 4 + 1]; //b = 1
bits[pix * 4 + 3] = pixels[pix * 4 + 2]; //a = 2
}
// and free the bit data.
return_value = bits;
width = FreeImage_GetWidth(dib);
height = FreeImage_GetHeight(dib);
}
}
GLuint image_loader::texture_loader(BYTE* texture, int width, int height) //this is called to upload the texture to the VGA
{
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture); //now we really can use RGBA format, hoooray!
return tex_id;
}
I call them like this:
render::fill_vbos(floor);
floor_texture.load_image_file("checker.png", floor, image_loader::TEXTURE);
that's how I render them:
void render::draw_meshes_vbo(const mesh& the_mesh)
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); //just enable the VBOs and draw them
// Here's where the data is now
glBindBuffer(GL_ARRAY_BUFFER, the_mesh.vbos[the_mesh.VERTEX_VBO]);
glVertexPointer(3, GL_FLOAT,0, 0);
// Normal data
glBindBuffer(GL_ARRAY_BUFFER, the_mesh.vbos[the_mesh.NORMAL_VBO]);
glNormalPointer(GL_FLOAT, 0, 0);
calling it like this:
modelview_stack.push_matrix();
modelview_stack.translate_matrix(mymath::vec3f(0.0f, -100.0f, 0.0f)); //we move the mesh below the camera, so that I can see it when I look down
the_pipeline.get_model_view_matrix().copy_m4x4_data(mv); //we copy the modelview & projection matrix data to normal float arrays so that we can pass them to the shaders
the_pipeline.get_projection_matrix().copy_m4x4_data(proj);
texturing_shader.use_program(); //use the shader
glUniformMatrix4fv(glGetUniformLocation(texturing_shader.shader_program, texturing_shader.resources[0].name.c_str()), 1, false, proj); //pass the matrices to the shader
glUniformMatrix4fv(glGetUniformLocation(texturing_shader.shader_program, texturing_shader.resources[1].name.c_str()), 1, false, mv);
//something is not right...
glActiveTexture(GL_TEXTURE0); //make the texture "active"
glBindTexture(GL_TEXTURE_2D, floor.texture); //bind it
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //set the settings so that it will repeat itself on the surface (floor)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUniform1i(glGetUniformLocation(texturing_shader.shader_program, texturing_shader.resources[2].name.c_str()), 0); //lets pass the texture
draw_meshes_vbo(floor); //draw the mesh
texturing_shader.return_to_fixed_program(); //return to fixed functionality (I dont really know if it has an effect in OGL 3.3)
You're using glTexCoordPointer with "in vec2 v2_texture;", that's not going to work. glTexCoordPointer only sends data to one special input variable (gl_MultiTexCoord[0] or something, can't quite remember).
Anyway that's deprecated anyway so you shouldn't be using it (or glVertexPointer, or glNormalPointer).
What you want to do is call glGetAttribLocation, and then use glVertexAttribPointer with your vertices, normals, and texcoords.
Also replace glEnableClientState with glEnableVertexAttribArray.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game