Still struggling with my water waves

Started by
4 comments, last by browny 19 years, 1 month ago
Heh, it seems all I do is struggle with this stuff... Anyway, getting some reallllly nasty results now - and I'm pretty clueless to how to solve the problem. I have my water represented by a nice simple quad, just 2 triangles and I render my reflection and refraction textures fine. I can apply these textures as a perfectly still water surface fine, but the problem comes when I try to add waves to this surface. I have a normal map that represents the waves, and here is my pixel shader showing how I am applying it all.

float4 FP_Projective(vsOut vsIn) : COLOR
{	
	float3 normalSample = tex2D(NormalMap, vsIn.texCoords);
	float3 normal = (normalSample / 127) - 1;
	
	vsIn.origPos.xz += normal.xz * 4;
	float4 texCoords = mul(vsIn.origPos, matRefl);

	float3 v = normalize(vsIn.viewDir);

	float4 refraction = tex2Dproj(RefractMap, texCoords);
	float4 reflection =  tex2Dproj(ReflectMap, texCoords);
	return lerp(refraction, reflection, tex2D(Fresnel, dot(normal, v)));
}
Now using a texture that consists of just (128, 255, 128) which should be a normal of [0, 1, 0] I get a totally messed up projection that is just well off. I thought that it should have absolutly no effect : Any ideas?
Ollie"It is better to ask some of the questions than to know all the answers." ~ James Thurber[ mdxinfo | An iridescent tentacle | Game design patterns ]
Advertisement
Well i think, when the texels arives at the pixel shaders.. they r all normalized to 0-1,so i dont think u would need to normalize them once again by dividing by 127. You should rather simple do this

normal = t*2 - 1;

Z
It looks like you are using Cg, is that correct?

I believe (I'm at work right now so I can't check) that all the texture lookup functions return values in the [0, 1] range. So your normalSample variable should be (0.5, 1.0, 0.5). Then your scale and bias should be this...
float3 normal = (normalSample*2.0f) - 1.0f;


EDiT: Damn, beaten by a lot. Took too long to look for cg docs online. :P
I could hug both of you. But seeing as I can't I just ++'ed you :)

Thanks sooooo much! One final question though: In my normal maps, the blue channel is always 255 resulting in the Z normal always being 1. I've combatted this problem by simply swapping the green and blue channels but this doesn't seem right... any ideas?
Ollie"It is better to ask some of the questions than to know all the answers." ~ James Thurber[ mdxinfo | An iridescent tentacle | Game design patterns ]
As normals tend to point away from the surface they will usually have a z component greater zero. So the blue component is present on most texels when doing tangent space normal mapping. When normals are in object or world space there are no constraints regarding the direction. If the blue channel of your normal map is always excatly 1 (or 255) then your normal map is not generated correctly as the vectors stored in it are not at unit length.

As you do normal mapping in world space and the positive y axis points up your normals should group around green (0,1,0).
Usually when normal maps are created.. the up vector is taken to be Z-Axis, which is not a problem at all because when u do the Dot3 stuffs you convert you light vector to the tangent space of the polygon ( which is defined by Tangent, Bi-Normal, and Normal vectors ). Hence , to find out the new Z-Ordinate of the light vector, so that it matches with the Z-Ordinate of ur normal map ( i.e the blue channel ) u do the dot product ot the light vector with the Normal Vector.

Ok, let me show u the mathematics

suppose we have a light vector ( in global coordiante ) V
and the tangent space of the polygon is defined by the vectors T ( Tangent ), B (Binormal) and N (normal). These vectors can be precaculated for every vertex and sent directly to the vertex shader and eventually to the pixel ( as texcoords )

Now to convert the Light vector V into the tangent space vector V', we do the following:

V'.x = B . V
V'.y = T . V
V'.z = N . V

See.. our V'.z is calculated by finding out the projection of V on N !!! and this is how it gets aligned with ur blue channel :P

Now to find out the diffuse componenent we simple Dot product the V' with the NormalMap. i.e.

Diffuse = NormalMap . V'

Now u can use this 'Diffuse' do modulate your pixel :p

By the way.. in the above calculation , all the vectors must be

1) Normalized, or least somewhat normalized, cuz when vectors are interpolated in pixel shader they get a lil de-normalized, but we can live with it

2) The normalmap is properly scaled and translated.. i.e.
normalmap = Texel * 2 - 1
is performed first

Yo! that was a nice math tutorial i guess :p
Z

This topic is closed to new replies.

Advertisement