PDA

View Full Version : Parallax mapping

10-23-2007, 07:48 PM
Why would parallax mapping be dependent on the light source direction? All the examples I have looked at tie it in with the light source.

I am using "radiosity bump mapping" which is a fancy way of saying I calculate a lightmap with a "light direction map" to tell the shader where light is coming from.

I don't see why parallax mapping needs to be tied to a light source, since it is a function of the eye vector and the height at that texel.

It's usually something like this:
float height = texture2D(heightmap,gl_TexCoord[0].st).a
height = height * 0.04 - 0.036;
newtexcoord = gl_TexCoord[0].st + height * normalize(halfvec).xy;

So I need the vector to multiply the height by. Why should this have anything to do with a light source?

CRasterImage
10-23-2007, 09:46 PM
I am not sure what your question is.
Can you describe the part light plays in your algorithm that doesn't seem necessary to you?

10-24-2007, 01:09 AM
I have bumpmapping implemented. It works perfectly, but it doesn't use a single light source like most examples do.

Now parallax mapping simply takes the normal and the eye vector and skews the texcoords a little. So I want to do this independently of the bumpmapping or lighting.

Vexator
10-24-2007, 01:44 AM
the eye vector is independent from the light's position.. it only depends on the camera'a position/rotation.

Ysaneya
10-24-2007, 07:41 AM
Given one of his constants is called "halfvec", I suppose he's using the half vector between the eye vector and the light direction, hence the original question :)

10-24-2007, 08:38 AM
Exactly. Every implementation I have seen uses a halfvec from a light source. They are probably merging some of their bumpmap / parallax mapping stuff, but there should be a way to do them separately. I mean, you should be able to do parallax mapping on a flat unlit texture with no bumpmap, just a heightmap.

CRasterImage
10-24-2007, 04:47 PM
We would need to see the code.
In the case of parallax mapping, the halfvec variable would need to be based on the polygon's normal. It shouldn't be based on light, I agree. The new texture coordinate shouldn't be relative to the position of a light source. (Or the half-vector between them) That would cause the coordinate offset to move depending on your position relative to a light source.

Can you post the whole sample?

10-24-2007, 04:55 PM
The important part is the parallax mapping section at the beginning, where basetexcoord is calculated. I am storing the heightmap in the colormap alpha channel (bumpmap alpha already gets used for specular level).

Thanks to Arne Reiners for his help with some of the bump stuff.

uniform sampler2D basetexture;
uniform sampler2D lightmap;
uniform sampler2D bumpmap;
uniform vec4 AmbientLight;
varying vec3 T,B,N;
varying vec3 ModelVertex;

void main(void) {

vec2 basetexcoord;
vec4 lightcolor;
vec4 bumpcolor;
float alpha=gl_Color.w;
vec3 lightdir;
vec3 normal;
vec4 basecolor;
float specular=0.0;

#ifdef LW_PARALLAX
vec3 h = normalize(halfVector);
float height = texture2D(heightMap,basetexcoord).r;
height = height * 0.04 - 0.036;
basetexcoord = gl_TexCoord[0].st + (height * h.xy);
#else
basetexcoord=gl_TexCoord[0].xy;
#endif

//======================================
// Light color
//======================================
#ifdef LW_LIGHTMAP
lightcolor = texture2D(lightmap,gl_TexCoord[1].st) * 2.0;

#ifdef LW_BUMPMAP
#endif
#else
lightcolor = gl_Color;
#endif

//======================================
// Bumpmap
//======================================
#ifdef LW_BUMPMAP

#ifdef LW_LIGHTMAP
lightdir = gl_NormalMatrix * ( ( texture2D(radiositymap,gl_TexCoord[1].st).xyz - 0.5 ));
#endif

vec3 halfvec = normalize(normalize(lightdir) + normalize(-ModelVertex));

bumpcolor = texture2D(bumpmap,basetexcoord);
normal = normalize(bumpcolor.xyz - 0.5);
normal = T * normal.x + B * normal.y + N * normal.z;

float diffuse = max(0.0,dot(normal,lightdir));
lightcolor = lightcolor * diffuse;
specular = pow(max(0.0, dot(halfvec,normal)),8.0) * bumpcolor.w;
#endif

//======================================
// Base color
//======================================
#ifdef LW_BASETEXTURE
basecolor = texture2D(basetexture,basetexcoord);// * gl_Color*2.0;
alpha *= basecolor.w;
#else
basecolor=vec4(0.5);
#endif

//======================================
// Mix final color
//======================================
gl_FragColor = basecolor * lightcolor;
#ifdef LW_BUMPMAP
gl_FragColor += specular * lightcolor * 2.0;
#endif
gl_FragColor += basecolor * AmbientLight;

//======================================
// Fog effect
//======================================
float fogeffect = clamp( 1.0 - (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale , 0.0, 1.0 ) * gl_Fog.color.w;
gl_FragColor = gl_FragColor * (1.0 - fogeffect) + gl_Fog.color * fogeffect;

gl_FragColor.w=alpha;
}

CRasterImage
10-24-2007, 06:34 PM
But where does the halfVector come from?
It isn't a global or a local variable.

10-24-2007, 06:51 PM
Lumina has a good example showing simple relief mapping, without any nonsense:
http://lumina.sourceforge.net

I used that as an example, and it works now:

CRasterImage
10-24-2007, 10:14 PM
You are getting 1014 frames per second?!

What kind of video card you got there?

10-24-2007, 11:37 PM
GE Force 8800.

Why should it be slow? This is the only parallax code in the frag shader:

vec3 eye = normalize(EyeVec);
float height = texture2D(basetexture,basetexcoord).a;
height = height * 0.04 - 0.036;
basetexcoord = basetexcoord + (height * eye.xy);

CRasterImage
10-25-2007, 12:27 AM
Well, I have a Geforce 6000-something and I can't get it to render faster than 90 frames per second, if I don't draw anything at all.

Are you sure your FPS calculations are correct?

1014 FPS seems pretty high.

10-25-2007, 12:31 AM

Relic
10-25-2007, 12:58 AM
Originally posted by CRasterImage:
Well, I have a Geforce 6000-something and I can't get it to render faster than 90 frames per second, if I don't draw anything at all.
Vsync on?
Switch the 3D settings in the NVIDIA display control panel for "vertical sysnc" to "force off" and remeasure.

Humus
10-29-2007, 03:32 PM
It's usually something like this:
float height = texture2D(heightmap,gl_TexCoord[0].st).a
height = height * 0.04 - 0.036;
newtexcoord = gl_TexCoord[0].st + height * normalize(halfvec).xy;

I've never seen any examples do something like that. That's obviously broken. Replace "halfvec" with "viewVec" and it should be OK.