I have a huge problem that I can't fix alone.
I've tested a normal mapping shader with shader designer and here is everything working.
But I have problems when I try to supply the T and B vectors to my shader. I don't even know if the calculation of my T and B vector is correct.
Here's the code.
the render function for every model
void objModel::draw(float cp[3]){
if(NormalMapping()||BlinnPhong()){
glUseProgram(buf->program.progName);
}
else
glUseProgramObjectARB(0);
glBindBuffer(GL_ARRAY_BUFFER,getVertexBuffer());
glVertexPointer(3,GL_FLOAT,sizeof(Vertex),(void*)0);
glEnableClientState(GL_VERTEX_ARRAY);
if(applyNormalToObj()){//normal mapping shader
glBindBuffer(GL_ARRAY_BUFFER,getNormalBuffer());
glNormalPointer(GL_FLOAT,sizeof(Vertex),(void*)0);
glEnableClientState(GL_NORMAL_ARRAY);
}
if(NormalMapping()){
glEnableVertexAttribArrayARB(getTangentBuffer());
glEnableVertexAttribArrayARB(getBinormalBuffer());
glVertexAttribPointerARB(getTangentBuffer(),3,GL_FLOAT,0,0,&par.Tangent[0]);
glVertexAttribPointerARB(getBinormalBuffer(),3,GL_FLOAT,0,0,&par.Binormal[0]);
glUniform1i(buf->uniforms.textures[0],0);
glUniform1i(buf->uniforms.textures[1],1);//i don't use this in the shader
glUniform1i(buf->uniforms.textures[2],2);//I don't use this in the shader
glUniform1i(buf->uniforms.textures[3],3);
glUniform1f(buf->uniforms.mat.shininess,kShi);
glUniform4fv(buf->uniforms.mat.diffuse,1,kDiff);
}
//this works well
if(BlinnPhong()){
glUniform4fv(buf->uniforms.mat.ambient,1,kAmb);
glUniform4fv(buf->uniforms.mat.diffuse,1,kDiff);
glUniform4fv(buf->uniforms.mat.specular,1,kSpec);
glUniform1f(buf->uniforms.mat.shininess,kShi);
glUniform3fv(buf->uniforms.campos,1,cp);
}
if(applyTextureToObj()){//se devo applicare le texture al modello...
//diffuse texture
glActiveTexture(GL_TEXTURE0);
glBindTexture ( GL_TEXTURE_2D, getTextureNameDiffuse() );
glBindBuffer(GL_ARRAY_BUFFER,getTextureBuffer());
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
if(apply3CoordTexture())
glTexCoordPointer(3,GL_FLOAT,sizeof(Texel),(void*)0);
else
glTexCoordPointer(2,GL_FLOAT,sizeof(GLfloat)*2,(void*)0);//sizeof(Texeluv)
//_________________________________________________________________________________
//specular texture
glActiveTexture(GL_TEXTURE1);
glBindTexture ( GL_TEXTURE_2D, getTextureNameSpecular() );
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindBuffer(GL_ARRAY_BUFFER,getTextureBuffer());
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if(apply3CoordTexture())
glTexCoordPointer(3,GL_FLOAT,sizeof(Texel),(void*)0);
else
glTexCoordPointer(2,GL_FLOAT,sizeof(GLfloat)*2,(void*)0);//sizeof(Texeluv)
//__________________________________________________________________________
//gloss or normal texture
glEnable(GL_TEXTURE_2D);
glBindTexture ( GL_TEXTURE_2D, getTextureNameGloss( ));
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindBuffer(GL_ARRAY_BUFFER,getTextureBuffer());
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if(apply3CoordTexture())
glTexCoordPointer(3,GL_FLOAT,sizeof(Texel),(void*)0);
else
glTexCoordPointer(2,GL_FLOAT,sizeof(GLfloat)*2,(void*)0);//sizeof(Texeluv)
if(NormalMapping()){
//__________________________________________________________________________
//normal map texture
glEnable(GL_TEXTURE_2D);
glBindTexture ( GL_TEXTURE_2D, getTextureNameNormal( ));
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindBuffer(GL_ARRAY_BUFFER,getTextureBuffer());
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if(apply3CoordTexture())
glTexCoordPointer(3,GL_FLOAT,sizeof(Texel),(void*)0);
else
glTexCoordPointer(2,GL_FLOAT,sizeof(GLfloat)*2,(void*)0);//sizeof(Texeluv)
}
}
if(getCullBack()){
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
if(getCullFront()){
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,getTIndeces());
glDrawElements(GL_TRIANGLES,getTIndecesSize(),GL_UNSIGNED_INT,(void*)0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,getQIndeces());
//glDrawElements(GL_QUADS,getQIndecesSize(),GL_UNSIGNED_INT,(void*)0);
if(NormalMapping()){
glDisableVertexAttribArrayARB(getTangentBuffer());
glDisableVertexAttribArrayARB(getBinormalBuffer());
}
if(getCullBack()|| getCullFront())
glDisable(GL_CULL_FACE);
if(applyNormalToObj())
glDisableClientState(GL_NORMAL_ARRAY);
if(applyTextureToObj()){
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisable(GL_TEXTURE_2D);
}
glDisableClientState(GL_VERTEX_ARRAY);
}
here I have the setup of the normal map shader
if(par.NormalMapping()){
createNormalMappingVShader1(nmvs);//these are two funcions that create the text files with the shader source code
createNormalMappingFShader1(nmfs);
cout << " normal mapping shader creati " << endl;
buffer->vertex_shader = make_shader(GL_VERTEX_SHADER,nmvs.c_str());
if (buffer->vertex_shader == 0)
return 0;
buffer->fragment_shader = make_shader(GL_FRAGMENT_SHADER,nmfs.c_str());
if (buffer->fragment_shader == 0)
return 0;
buffer->program.progName = make_program(buffer->vertex_shader, buffer->fragment_shader);
if (buffer->program.progName == 0)
return 0;
buffer->uniforms.textures[0]=glGetUniformLocation(buffer->program.progName,"base");
buffer->uniforms.textures[1]=glGetUniformLocation(buffer->program.progName,"specularTexture");
buffer->uniforms.textures[2]=glGetUniformLocation(buffer->program.progName,"glossTexture");
buffer->uniforms.textures[3]=glGetUniformLocation(buffer->program.progName,"normalMap");
buffer->uniforms.mat.diffuse=glGetUniformLocation(buffer->program.progName,"kdiff");
buffer->uniforms.mat.shininess=glGetUniformLocation(buffer->program.progName,"kshi");
buffer->attributes.tangent=glGetAttribLocation(buffer->program.progName, "tangent");
glBindAttribLocation(buffer->program.progName,buffer->attributes.tangent,"tangent");
buffer->attributes.binormal=glGetAttribLocation(buffer->program.progName, "binormal");
glBindAttribLocation(buffer->program.progName,buffer->attributes.binormal,"binormal");
tangent space calculation
std::vector <int> nTimes;
if(NormalMapping()){
//init tantent
Vertex zero;
zero.x=zero.y=zero.z=0.0;
for(int a=0;a<NewVertex.size();a++) {
Tangent.push_back(zero);
Binormal.push_back(zero);
nTimes.push_back(0);
}
for(int a=0;a<triangle_elements.size();a++){
if((a%3)==0){
int i1,i2,i3;
i1=triangle_elements.at(a);
i2=triangle_elements.at(a+1);
i3=triangle_elements.at(a+2);
Vertex v1,v2,v3;
Texeluv t1,t2,t3;
v1.x=NewVertex[i1].x;
v1.y=NewVertex[i1].y;
v1.z=NewVertex[i1].z;
t1.u=NewTexeluv[i1].u;
t1.v=NewTexeluv[i1].v;
v2.x=NewVertex[i2].x;
v2.y=NewVertex[i2].y;
v2.z=NewVertex[i2].z;
t2.u=NewTexeluv[i2].u;
t2.v=NewTexeluv[i2].v;
v3.x=NewVertex[i3].x;
v3.y=NewVertex[i3].y;
v3.z=NewVertex[i3].z;
t3.u=NewTexeluv[i3].u;
t3.v=NewTexeluv[i3].v;
Tangent.at(i1)=somma(Tangent.at(i1),(generateTangent(v1,v2,v3,t1,t2,t3)));
Tangent.at(i2)=somma(Tangent.at(i2),(generateTangent(v1,v2,v3,t1,t2,t3)));
Tangent.at(i3)=somma(Tangent.at(i3),(generateTangent(v1,v2,v3,t1,t2,t3)));
Binormal.at(i1)=somma(Binormal.at(i1),(generateBinormal(v1,v2,v3,t1,t2,t3)));
Binormal.at(i2)=somma(Binormal.at(i2),(generateBinormal(v1,v2,v3,t1,t2,t3)));
Binormal.at(i3)=somma(Binormal.at(i3),(generateBinormal(v1,v2,v3,t1,t2,t3)));
nTimes.at(i1)++;
nTimes.at(i2)++;
nTimes.at(i3)++;
}
}
}
if(NormalMapping()){
for(int v=0;v<NewVertex.size();v++){
if(nTimes.at(v)!=0){
Tangent.at(v).x=Tangent.at(v).x/nTimes.at(v);
Tangent.at(v).y=Tangent.at(v).y/nTimes.at(v);
Tangent.at(v).z=Tangent.at(v).z/nTimes.at(v);
Binormal.at(v).x=Binormal.at(v).x/nTimes.at(v);
Binormal.at(v).y=Binormal.at(v).y/nTimes.at(v);
Binormal.at(v).z=Binormal.at(v).z/nTimes.at(v);
}
}
}
if(NormalMapping()){
for(int v=0;v<NewVertex.size();v++){
// Gram-Schmidt orthogonalize
Tangent.at(v).x=Tangent.at(v).x- NewNormal.at(v).x*(NewNormal.at(v).x*Tangent.at(v).x+NewNormal.at(v).y*Tangent.at(v).y+NewNormal.at(v).z*Tangent.at(v).z);
Tangent.at(v).y=Tangent.at(v).y- NewNormal.at(v).y*(NewNormal.at(v).x*Tangent.at(v).x+NewNormal.at(v).y*Tangent.at(v).y+NewNormal.at(v).z*Tangent.at(v).z);
Tangent.at(v).z=Tangent.at(v).z- NewNormal.at(v).z*(NewNormal.at(v).x*Tangent.at(v).x+NewNormal.at(v).y*Tangent.at(v).y+NewNormal.at(v).z*Tangent.at(v).z);
Tangent.at(v)=normalize(Tangent.at(v));
if((Tangent.at(v).x*Tangent.at(v).x)!=0)
Binormal.at(v).x=Binormal.at(v).x- NewNormal.at(v).x*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).x)/(Tangent.at(v).x*Tangent.at(v).x);
else
Binormal.at(v).x=Binormal.at(v).x- NewNormal.at(v).x*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).x);
if((Tangent.at(v).y*Tangent.at(v).y)!=0)
Binormal.at(v).y=Binormal.at(v).y- NewNormal.at(v).y*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).y)/(Tangent.at(v).y*Tangent.at(v).y);
else
Binormal.at(v).y=Binormal.at(v).y- NewNormal.at(v).y*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).y);
if((Binormal.at(v).z*Binormal.at(v).z)!=0)
Binormal.at(v).z=Binormal.at(v).z- NewNormal.at(v).z*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).z)/(Tangent.at(v).z*Tangent.at(v).z);
else
Binormal.at(v).z=Binormal.at(v).z- NewNormal.at(v).z*(NewNormal.at(v).x*Binormal.at(v).x+NewNormal.at(v).y*Binormal.at(v).y+NewNormal.at(v).z*Binormal.at(v).z)-((Tangent.at(v).x*Binormal.at(v).x+Tangent.at(v).y*Binormal.at(v).y+Tangent.at(v).z*Binormal.at(v).z)*Tangent.at(v).z);
Binormal.at(v)=normalize(Binormal.at(v));
}
}
Vertex parser::generateTangent(Vertex v1, Vertex v2, Vertex v3, Texeluv tex1, Texeluv tex2,Texeluv tex3)
{
Vertex Q1,Q2;
Q1.x=v2.x-v1.x;
Q1.y=v2.y-v1.y;
Q1.z=v2.z-v1.z;
Q2.x=v3.x-v1.x;
Q2.y=v3.y-v1.y;
Q2.z=v3.z-v1.z;
float u1=tex2.u-tex1.u;
float vi1=tex2.v-tex1.v;
float u2=tex3.u-tex1.u;
float vi2=tex3.v-tex1.v;
float coef = 0.0f;
if(fabsf(u1* vi2 - u2 * vi1)<= 0.0001f)
coef=1.0;
else
coef = 1/ (u1* vi2 - u2 * vi1);
Vertex tangent;
tangent.x=coef*(vi2*Q1.x-vi1*Q2.x);
tangent.y=coef*(vi2*Q1.y-vi1*Q1.y);
tangent.z=coef*(vi2+Q1.x-vi1*Q1.z);
return normalize(tangent);
}
Vertex parser::generateBinormal(Vertex v1, Vertex v2, Vertex v3, Texeluv tex1, Texeluv tex2,Texeluv tex3)
{
Vertex Q1,Q2;
Q1.x=v2.x-v1.x;
Q1.y=v2.y-v1.y;
Q1.z=v2.z-v1.z;
Q2.x=v3.x-v1.x;
Q2.y=v3.y-v1.y;
Q2.z=v3.z-v1.z;
float u1=tex2.u-tex1.u;
float vi1=tex2.v-tex1.v;
float u2=tex3.u-tex1.u;
float vi2=tex3.v-tex1.v;
float coef;
if(fabsf(u1* vi2 - u2 * vi1)<= 0.0001f)
coef=1.0;
else
coef = 1/ (u1* vi2 - u2 * vi1);
Vertex binormal;
binormal.x=coef*(-u2*Q1.x-u1*Q2.x);
binormal.y=coef*(-u2*Q1.y-u1*Q1.y);
binormal.z=coef*(-u2+Q1.x-u1*Q1.z);
return normalize(binormal);
}
that's should be everything... thanks