Hello all, I am trying to implement a parallactic GLSL shader, but I got stuck on handedness of my generated tangent space. I can’t for the life of me find a way to make this thing work properly. Here’s a screenshot of what I m getting
http://www.ramiriccardo.com/nlcachef/sshots/parallax-seams.jpg
The problem is with those visible triangles on the wing. It should be smooth, but it is not.
Here is my code to generate the tangent space…
private void createTangentSpace(){
//Creates a tangent space to be used with
//per-pixel lighting
meshes.reset();
Mesh currentMesh=null;
while((currentMesh=(Mesh)meshes.getNext())!=null){
for(int i=0;i<currentMesh.numFaces;i++){
//Find the tangent basis
Vector3f p1=new Vector3f(currentMesh.vertices[currentMesh.faces[i].vertices[0]].m_location);
Vector3f p2=new Vector3f(currentMesh.vertices[currentMesh.faces[i].vertices[1]].m_location);
Vector3f p3=new Vector3f(currentMesh.vertices[currentMesh.faces[i].vertices[2]].m_location);
Vector2f uv1=new Vector2f(currentMesh.vertices[currentMesh.faces[i].vertices[0]].m_texCoords);
Vector2f uv2=new Vector2f(currentMesh.vertices[currentMesh.faces[i].vertices[1]].m_texCoords);
Vector2f uv3=new Vector2f(currentMesh.vertices[currentMesh.faces[i].vertices[2]].m_texCoords);
Vector3f Edge1 = p2.subtract(p1);
Vector3f Edge2 = p3.subtract(p1);
Vector2f Edge1uv = uv2.subtract(uv1);
Vector2f Edge2uv = uv3.subtract(uv1);
float cp = Edge1uv.y * Edge2uv.x - Edge1uv.x * Edge2uv.y;
if ( cp != 0.0f ) {
float mul = 1.0f / cp;
currentMesh.faces[i].tangent = Edge1.mulByf(-Edge2uv.y).sum(Edge2.mulByf(Edge1uv.y)).mulByf(mul);
currentMesh.faces[i].biTangent = Edge1.mulByf(-Edge2uv.x).sum(Edge2.mulByf(Edge1uv.x)).mulByf(mul);
currentMesh.faces[i].tangent.normalize();
currentMesh.faces[i].biTangent.normalize();
}
}
//Now smoothen the vectors accross the vertices.
for(int i=0;i<currentMesh.vertices.length;i++){
int[] neighbors = currentMesh.findVertexOwnerFaces(i);
Vector3f vecTangent=new Vector3f();
Vector3f vecBiTangent=new Vector3f();
Vector3f vecNormal=new Vector3f(currentMesh.vertices[i].m_normal[0],
currentMesh.vertices[i].m_normal[1],
currentMesh.vertices[i].m_normal[2]);
for(int n=0;n<neighbors.length;n++){
vecTangent.sumOW(currentMesh.faces[neighbors[n]].tangent);
vecBiTangent.sumOW(currentMesh.faces[neighbors[n]].biTangent);
}
vecTangent.normalizeOW();
vecBiTangent.normalizeOW();
//Gram-Schmidt orthogonalization
vecTangent.subtractOW(vecNormal.mulByf(vecTangent.dotProduct(vecNormal)));
vecTangent.normalize();
vecBiTangent.subtractOW(vecNormal.mulByf(vecBiTangent.dotProduct(vecNormal)));
vecBiTangent.normalize();
currentMesh.vertices[i].m_tangent[0]=vecBiTangent.x;
currentMesh.vertices[i].m_tangent[1]=vecBiTangent.y;
currentMesh.vertices[i].m_tangent[2]=vecBiTangent.z;
currentMesh.vertices[i].m_bitangent[0]=vecTangent.x;
currentMesh.vertices[i].m_bitangent[1]=vecTangent.y;
currentMesh.vertices[i].m_bitangent[2]=vecTangent.z;
}
}
}
The Vertex shader:
attribute vec3 rm_Tangent;
attribute vec3 rm_Binormal;
varying vec3 g_lightVec;
varying vec3 g_viewVec;
void main()
{
float u_invRad =1.0/50.0;
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
vec3 binormal=cross(rm_Tangent.xyz, gl_Normal);
mat3 TBN_Matrix = gl_NormalMatrix * mat3(rm_Tangent, rm_Binormal, gl_Normal);
vec4 mv_Vertex = gl_ModelViewMatrix * gl_Vertex;
g_viewVec = vec3(-mv_Vertex) * TBN_Matrix;
vec4 light = gl_ModelViewMatrix * gl_LightSource[1].position;
vec3 lightVec = u_invRad * (light.xyz - mv_Vertex.xyz);
g_lightVec = lightVec * TBN_Matrix;
}
And finally the Fragment shader:
uniform sampler2D bump_map;
uniform sampler2D rgb_map;
varying vec3 g_lightVec;
varying vec3 g_viewVec;
void main()
{
vec2 cBumpSize=0.01 * vec2 (2.0, -1.0);
float LightAttenuation = clamp(1.0 - dot(g_lightVec, g_lightVec), 0.0, 1.0);
vec3 lightVec = normalize(g_lightVec);
vec3 viewVec = normalize(g_viewVec);
float height = texture2D(bump_map, gl_TexCoord[0].xy).r;
height = height * cBumpSize.x + cBumpSize.y;
vec2 newUV = gl_TexCoord[0].xy + viewVec.xy * height;
vec4 color_base = texture2D(rgb_map,newUV);
vec3 bump = texture2D(bump_map, newUV.xy).rgb * 2.0 - 1.0;
bump = normalize(bump);
float diffuse = clamp(dot(lightVec, bump), 0.0, 1.0);
float specular = pow(clamp(dot(reflect(-viewVec, bump), lightVec), 0.0, 1.0), 16.0);
gl_FragColor = 3.0*color_base * gl_LightSource[1].diffuse
* (diffuse * base + 3.0*specular);
gl_FragColor = 0.2*color_base+(0.2* gl_FragColor)+gl_FragColor;
gl_FragColor.a = 1.0;
}
I m losing it trying to figure out what I m doing wrong… I’d be very grateful if anyone could help me out.
Thanks.