c++ - OpenGL 3.1 Issue rendering textures with indexed drawing -


i'm trying use gldrawelements draw model loaded assimp, geometry displays fine textures dont show on model, black version of model i've loaded.

load model function

modelinfo loadmodel(const std::string& modelpath){ printf( "loading model: %s\n", modelpath.c_str()); //verify file exists first std::ifstream fin(modelpath.c_str()); if(!fin.fail()){     fin.close(); }else{     throw std::runtime_error("could not open file" + modelpath); }  assimp::importer importer; const aiscene* scene = importer.readfile( modelpath,         aiprocesspreset_targetrealtime_fast |         //aiprocess_calctangentspace      |         aiprocess_triangulate           |         aiprocess_gensmoothnormals      |         aiprocess_flipuvs     //aiprocess_joinidenticalvertices |     //aiprocess_sortbyptype); );  if(!scene){     throw std::runtime_error(importer.geterrorstring()); } printf("imported %s\n",modelpath.c_str()); fflush(stdout);  std::vector<unsigned int> indices; std::vector<float> vertices; std::vector<float> uvs; std::vector<float> normals;  aimesh* mesh = scene->mmeshes[0];  int numoffaces = mesh->mnumfaces; int numofindices = numoffaces * 3; indices.resize(numofindices);  (unsigned int =0; < mesh->mnumfaces; ++i){     const aiface &face = mesh->mfaces[i];     assert(face.mnumindices == 3);     indices[i * 3 + 0] = face.mindices[0];     indices[i * 3 + 1] = face.mindices[1];     indices[i * 3 + 2] = face.mindices[2]; }  int numofvertices = mesh->mnumvertices; vertices.resize(numofvertices * 3); normals.resize(numofvertices * 3); uvs.resize(numofvertices * 2); for( unsigned int = 0; < mesh->mnumvertices; ++i){     if(mesh->haspositions()){         vertices[i * 3 + 0] = mesh->mvertices[i].x;         vertices[i * 3 + 1] = mesh->mvertices[i].y;         vertices[i * 3 + 2] = mesh->mvertices[i].z;         //printf("[ %f, %f, %f]\n",vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]);     }       if( mesh->hasnormals()){         normals[i * 3 + 0] = mesh->mnormals[i].x;         normals[i * 3 + 1] = mesh->mnormals[i].x;         normals[i * 3 + 2] = mesh->mnormals[i].x;     }      if(mesh->hastexturecoords(0)){         uvs[i * 2 + 0] = mesh->mtexturecoords[0][i].x;         uvs[i * 2 + 1] = mesh->mtexturecoords[0][i].y;         printf("[ %f, %f]\n",uvs[i*2+0],uvs[i*2+1]);     } }  //create voa gluint vao; glgenvertexarrays(1, &vao); glbindvertexarray(vao); //create element buffer gluint elementbuffer; glgenbuffers(1, &elementbuffer); glbindbuffer(gl_element_array_buffer, elementbuffer); glbufferdata(gl_element_array_buffer, indices.size() * sizeof(unsigned int), &indices[0], gl_static_draw);  //create vertex buffer gluint vertexbuffer; glgenbuffers(1, &vertexbuffer); glbindbuffer(gl_array_buffer, vertexbuffer); glbufferdata(gl_array_buffer, vertices.size() * sizeof(aivector3d), &vertices[0], gl_static_draw);  glenablevertexattribarray(0); glvertexattribpointer(0, 3, gl_float, gl_false, 3 * sizeof(float), (void*)0); printf("vertices.size %lu\n", vertices.size()); printf("uvs.size %lu\n", uvs.size());  gluint uvbuffer; glgenbuffers(1, &uvbuffer); glbindbuffer(gl_array_buffer, uvbuffer); glbufferdata(gl_array_buffer, uvs.size() * sizeof(aivector2d), &uvs[0], gl_static_draw); glenablevertexattribarray(1); glvertexattribpointer(1, 2, gl_float, gl_false, 2*sizeof(float), (void*)0);  gluint normalbuffer; glgenbuffers(1, &normalbuffer); glbindbuffer(gl_array_buffer, normalbuffer); glbufferdata(gl_array_buffer, normals.size() * sizeof(aivector3d), &normals[0], gl_static_draw); glenablevertexattribarray(2); glvertexattribpointer(2, 3, gl_float, gl_false, 3 * sizeof(float), (void*)0);  modelinfo retval; retval.vao    = vao; retval.index  = elementbuffer; retval.vertex = vertexbuffer; retval.uv     = uvbuffer; retval.normal = normalbuffer; retval.count  = numofindices;  return retval; 

}

short overview of load model, loads model assimp, loads data first mesh in assimp scene vectors, creates vao, vbos geometry, texture coordinates, normals, , indexes. data loaded buffers vectors , vertex attributes set. once loaded struct containing several gluints created return data.

render model function

void render_model(modelinfo info){ cleanup(); //set program gluseprogram(modelprogram);  //set uniforms glm::mat4 view = camera.matrix(); gluniformmatrix4fv(modelcamera, 1, gl_false, &view[0][0]);  glm::mat4 model = glm::mat4(); model = glm::rotate(model, degree, glm::vec3(0,1,1));  gluniformmatrix4fv(modelmodel, 1, gl_false, &model[0][0]);  glbindvertexarray(info.vao);  glbindtexture(gl_texture_2d, texture); gluniform1i(modeltext, texture); gldrawelements(gl_triangles, info.count, gl_unsigned_int, (void*)0); } 

brief overview of render model. set shader program handle rendering model, matrix camera, pass shader, generate matrix model, make spin, pass shader. bind vao of model rendered. bind loaded text, used on other geometry in program shows no problem, pass shader. set, call gldrawelements starting first position in index buffer of current vao. once drawing complete clean unbind buffers , arrays

the shaders i'm using basic vertex shader

#version 140 uniform mat4 camera; uniform mat4 model;  in vec3 position; in vec2 uv;  out vec2 fraguv;  void main(){     //pass variables on fragment shader     fraguv   = uv;      //vertex draw     gl_position = camera * model * vec4(position,1); } 

fragment shader #version 140

uniform sampler2d modeltext;  in vec2 fraguv;  out vec4 finalcolor;  void main(){      finalcolor = texture(modeltext, fraguv); } 

all uniforms loaded correctly function verifies loaded, texture used , works else in program. model has texture coordinates. geometry loading , rendering no problem

you passing wrong value sampler uniform.

glbindtexture (gl_texture_2d, texture); gluniform1i   (modeltext,     texture); 

sampler uniforms not take name (id) of texture object, take index of texture image unit bound texture to. in example, appear using default texture image unit: gl_texture0, value sampler uniform should use 0.

because sampler2d expects texture image unit , not name of texture, never have change uniform when change bound texture. glsl sample whatever texture bound corresponding texture image unit (assuming have compatible types / states).

this means set sampler uniforms once when initialize glsl program , never touch again. in newer versions of glsl (4.20) can hard-code texture image unit sampler uses in shader itself, since using glsl 1.40 not have option unless extension: gl_arb_shading_language_420pack supported.


consider following code, correctly demonstrates how use sampler uniforms:

glactivetexture (gl_texture0); glbindtexture   (gl_texture_2d, texture); gluniform1i     (modeltext,     0); 

i have included redundant call glactivetexture (...) merely demonstrate how uniform sampler , active texture unit related... not pass constant gl_texture0 sampler, instead use integer index. gl_texture0 default active texture unit.


Comments

Popular posts from this blog

PHPMotion implementation - URL based videos (Hosted on separate location) -

javascript - Using Windows Media Player as video fallback for video tag -

c# - Unity IoC Lifetime per HttpRequest for UserStore -