PDA

View Full Version : Simple Parallax Mapping not working properly



djmj10
10-09-2008, 07:57 AM
Hi, after my per pixel lightning and bump map shaders which work fine I now try to realize parallax mapping, first without occlusion and relief.

I read many tutorials about it and understood the math behind it.

In Vertex Shader my view or eye vector is converted to tangentspace:

I read out the height from the heightmap with and multiply it with the uniforms depthStrength and add bias:



offset_depth = (texture2D(normalMap, texCoord).a) * depthStrength + bias;

this offset gets multiplied with the viewVector which is in tangentspace


offset = offset_depth * viewVector_t.xy;

then I use this offset for my diffuse and normal texture coordinates:


diffuseMap = texture2D(textureDiffuse, texCoord + offset);
normal_t = texture2D(normalMap, texCoord + offset).rgb * 2.0 - 1.0;



here my vertex shader:

<div class="ubbcode-block"><div class="ubbcode-header">Warning, Spoiler: <input type="button" class="form-button" value="Show" onclick="if (this.parentNode.parentNode.getElementsByTagName(' div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('d iv')[1].getElementsByTagName('div')[0].style.display = '';this.innerText = ''; this.value = 'Hide'; } else { this.parentNode.parentNode.getElementsByTagName('d iv')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Show'; }" />]<div style="display: none;">

//uniforms

uniform float LightSourceconstantAttenuation, LightSourcelinearAttenuation, LightSourcequadraticAttenuation;
uniform vec4 LightSourcePosition;

//varyings

varying float attenuation, nxOL ;
varying vec3 viewVector_t, lightVector_t, viewVector_v, normal_v;

//attributes

attribute vec3 Tangent;

//constants

//functions initialising

vec3 ConvertToTangent(vec3 c_vec, vec3 tangent, vec3 binormal, vec3 normal);

////////////////
//////Main//////
////////////////

void main()
{

////////////////
//initialising//
////////////////

float dist;
vec3 position_v, tangent_v, viewVector_v, binormal_v, v,
normal_v, lightVector_v, lightVector_w;

/////////////////////
//global references//
/////////////////////

gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

///////////////
////vectors////
///////////////

///////////////
//viewspace_v//
///////////////
normal_v = normalize(gl_NormalMatrix * gl_Normal);
tangent_v = normalize(gl_NormalMatrix * Tangent);
binormal_v = cross(normal_v, tangent_v);
position_v = vec3(gl_ModelViewMatrix * gl_Vertex);
viewVector_v = normalize(-position_v);
lightVector_v = LightSourcePosition.xyz - position_v;


////////////////
//worldspace_w//
////////////////

lightVector_w = LightSourcePosition.xyz - gl_Vertex.xyz;

//////////////////
//tangentspace_t//
//////////////////

v = ConvertToTangent(lightVector_v, tangent_v, binormal_v, normal_v);
lightVector_t = v;
v = ConvertToTangent(viewVector_v, tangent_v, binormal_v, normal_v);
viewVector_t = v;

////////////////
//calculations//
////////////////

dist = length(lightVector_w);

lightVector_v = normalize(lightVector_v);

attenuation = 1.0 / (LightSourceconstantAttenuation +
LightSourcelinearAttenuation * dist +
LightSourcequadraticAttenuation * pow(dist,2.0));

//parallax offset

nxOL = dot(normal_v, viewVector_v);

}

/////////////////////
//////Functions//////
/////////////////////

//This function converts the incoming vector c_vec to tangent space;

vec3 ConvertToTangent(vec3 c_vec, vec3 t, vec3 b, vec3 n) {
vec3 v;
v.x = dot(c_vec, t);
v.y = dot(c_vec, b);
v.z = dot(c_vec, n);
return v;
}
[/QUOTE]</div>

here the fragment shader:

<div class="ubbcode-block"><div class="ubbcode-header">Warning, Spoiler: <input type="button" class="form-button" value="Show" onclick="if (this.parentNode.parentNode.getElementsByTagName(' div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('d iv')[1].getElementsByTagName('div')[0].style.display = '';this.innerText = ''; this.value = 'Hide'; } else { this.parentNode.parentNode.getElementsByTagName('d iv')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = 'Show'; }" />]<div style="display: none;">
//uniforms

uniform float FrontMaterialshininess, depthStrength, bias;
uniform vec4 LightSourcediffuse, LightSourceambient, LightSourcespecular;
uniform sampler2D textureDiffuse, normalMap;

//varyings

varying float attenuation, nxOL;
varying vec3 viewVector_t, lightVector_t, viewVector_v;

//attributes

//constants

//functions initialising

////////////////
//////Main//////
////////////////

void main()
{

////////////////
//initialising//
////////////////
vec2 offset, texCoord;
vec3 reflectVector, normal_t;
vec4 diffuse, specular, diffuseMap;
float nxDir, specularPower, nxHalf, offset_depth;

///////////
//vectors//
///////////

//////////////////
//tangentspace_t//
//////////////////

viewVector_t = normalize(viewVector_t);
lightVector_t = normalize(lightVector_t);

////////////
//textures//
////////////
texCoord = vec2(gl_TexCoord[0].s * 12.0, gl_TexCoord[0].t * 3.5);

offset_depth = (texture2D(normalMap, texCoord).a) * depthStrength + bias;
offset = offset_depth * viewVector_t.xy;

diffuseMap = texture2D(textureDiffuse, texCoord + offset);
normal_t = texture2D(normalMap, texCoord + offset).rgb * 2.0 - 1.0;




///////////
//diffuse//
///////////

nxDir = max(0.0, dot(normal_t, lightVector_t));
diffuse = LightSourcediffuse * nxDir * attenuation;

////////////
//Specular//
////////////

specular = vec4 (0.0);
specularPower = 0.0;

if(nxDir != 0.0) {
reflectVector = normalize(reflect(-lightVector_t, normal_t));
reflectVector = normalize(2.0 * dot(normal_t, lightVector_t)* normal_t - lightVector_t);
nxHalf = max(0.0, dot(reflectVector, normal_t));
specularPower = pow(nxHalf, FrontMaterialshininess);
specular = LightSourcespecular * specularPower * attenuation;
}

////////////
//Parallax//
////////////


////////////////
//output color//
////////////////

gl_FragColor = ((diffuse + LightSourceambient) ) * vec4(diffuseMap.rgb, 1.0) +
(specular * diffuseMap.a);

}
[/QUOTE]</div>

At some positions the parallax effect looks fine, if I rotate the cylinder, the offset is wrong (red) and should be like the yellow arrows.

http://img383.imageshack.us/img383/3192/parallaxwrongdirectionxm6.th.jpg (http://img383.imageshack.us/my.php?image=parallaxwrongdirectionxm6.jpg)http://img383.imageshack.us/images/thpix.gif (http://g.imageshack.us/thpix.php)

Since hours I try to solve this but I have no idea.

thanks for help in advance