I've been spending the last couple of nights trying to get a nice parallax mapping shader working.
I've had some sucesss - in most cases, it works and looks pretty good.
I'm using a cube as a test object. On some sides of the cube, the offset may not be quite in the right direction, and on others, at certain angles the parallax offset effect because far greater than normal, and at a different angle much less than normal.
The screenshot I'm posting is just one case. If you need more to illustrate the problem I'm trying to describe, just ask.
I think it might be the way I'm calculating the
tangent space view vector, but I don't know for sure.
I also have a similar problem with the lighting (inconsistancy accross the faces/angles/directions).
Vertex Program (GLSL):
Code:
attribute vec3 tangent;
uniform vec4 viewPos; //object space
uniform vec4 lightPos; //object space - not used
varying vec3 normal;
varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoords;
void main(void)
{
vec3 vertex = (gl_ModelViewMatrix*gl_Vertex).xyz;
vec3 vertexInv = (gl_ModelViewMatrixInverse*gl_Vertex).xyz;
normal = normalize(gl_NormalMatrix*gl_Normal);
vec3 bitangent = cross(normal, tangent);
mat3 tbn = mat3(tangent, bitangent, normal);
vec3 L = normalize(gl_LightSource[0].position.xyz-vertex);
lightVec = L*tbn;
vec3 E = viewPos.xyz-gl_Vertex.xyz;
eyeVec = E*tbn;
eyeVec *= vec3(1,-1,1);
texCoords = gl_MultiTexCoord0.xy;
gl_Position = ftransform();
}
Fragment Shader (GLSL - parallax shifting code highlighted)
Code:
uniform sampler2D baseMap;
uniform sampler2D bumpMap; //requires 32-bit texture - parallax map in alpha channel
varying vec3 normal;
varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoords;
const float scale = 0.05;
const float bias = -scale/2.0;
vec3 unpackVec(vec4 v)
{
return v.xyz * 2.0 - 1.0;
}
void main(void)
{
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float height = texture2D(bumpMap, texCoords).a*scale+bias;
vec2 parallax = texCoords + height * E.xy;
vec3 bump = texture2D(bumpMap, parallax).xyz*2.0 - 1.0;
bump = normalize(bump);
vec3 reflVec = (2.0*dot(bump, L))*bump - L;
vec4 ambient = gl_LightSource[0].ambient*gl_FrontMaterial.ambient;
vec4 diffuse = (texture2D(baseMap, parallax)*gl_LightSource[0].diffuse*gl_FrontMaterial.diffuse)*max(dot(bump, L), 0.0);
vec4 specular = gl_LightSource[0].specular*gl_FrontMaterial.specular*pow(max(dot(reflVec, E), 0.0), gl_FrontMaterial.shininess);
gl_FragColor = ambient+diffuse+specular;
}