PDA

View Full Version : Mixing 2 normal maps



Nowhere-01
07-19-2011, 03:08 AM
Hey, i was trying to make animated textures lately, and make them blend smoothly between frames. But i came across the problem: i'm not really sure how mix two normal maps. Using simple mix function with 2 textures and blend factor works for diffuse, but it makes specular act incorrectly. the closer blend factor to 0.5, the lower specular intensity. So it creates pulsating effect during animation. But i can't compensate it or find the reason. It also makes reflection coord to offset with simmilar amplitute.

i calculate specular like that:
pow(clamp(dot(eyeDir, reflect(-lightDir, normalMap)), 0.0, 1.0), Shininess) * Specular_Intensity;

tried to multiplicate specular with 1.0 - abs(BlendFactor - 0.5), with different values\variations\scale - it didn't help.

I'm asking here because i'm not shure if that's a correct way. And maybe someone dealt with simillar problems or any ideas how to avoid that.

Nowhere-01
07-19-2011, 04:02 AM
i've just realized how stupid my question was. sorry. obviously, i need to blend results of lambert\specular calculation for both textures, not normal map samples(or find a way how to correctly blend them). that will reduce performance too much(yeah, i will use that shader on quite few objects...so maybe i should give it a try).

tksuoran
07-19-2011, 05:06 AM
Check out this:

http://diaryofagraphicsprogrammer.blogspot.com/2009/01/partial-derivative-normal-maps.html

Don't forget to read all the comments, especially the last two.

Nowhere-01
07-20-2011, 02:58 AM
Thank's for the reply and the link, tksuoran. But i can't test it, for some reason, normalziing normal map makes specular intensity extremely low(something about 0.00000001) and too sensitive to angles.

parts of code(where i think might be mistake)


vec4 T = -normalize(vec4(gl_NormalMatrix * Tangent, 1.0));
vec4 N = normalize(vec4(gl_NormalMatrix * gl_Normal, 1.0));
vec4 B = vec4(cross(N.xyz, T.xyz), 1.0);

vec4 Vertex = gl_ModelViewMatrix * gl_Vertex;
vec4 lv = gl_LightSource[0].position - Vertex;
lightDir.x = dot(lv, B);
lightDir.y = dot(lv, T);
lightDir.z = dot(lv, N);
lightDir.w = 1.0;
lightDir = normalize(lightDir);

vec4 vInverse = -Vertex;
eyeDir.x = dot(vInverse, B);
eyeDir.y = dot(vInverse, T);
eyeDir.z = dot(vInverse, N);
eyeDir.w = 1.0;
eyeDir = normalize(eyeDir);



vec4 Color = texture2D(colorMap, gl_TexCoord[0].xy);
vec4 bump = texture2D(bumpMap, gl_TexCoord[0].xy);
vec4 bump2 = texture2D(bumpMap2, gl_TexCoord[0].xy);
bump = normalize(mix(bump, bump2, BlendFactor) * 2.0 - 1.0);

float Lambert = clamp(dot(lightDir, bump), 0.0, 1.0);
float Spec = max(dot(bump, normalize(lightDir + eyeDir)), 0.0);
Spec = pow(Spec, Shininess) * Intensity;

Nowhere-01
07-20-2011, 05:34 AM
fixed by removing w - value from light calculations, because i'm not really sure how to handle it.

and i've tried to use derivate like that:


vec3 bump = texture2D(bumpMap, gl_TexCoord[0].xy).xyz;
bump.xy /= bump.z;
bump.z = 1.0;

vec3 bump2 = texture2D(bumpMap2, gl_TexCoord[0].xy).xyz;
bump2.xy /= bump2.z;
bump2.z = 1.0;

bump = normalize(mix(bump, bump2, BlendFactor) * 2.0 - 1.0);

And that actually made things look a bit worse in comparsion with simply blending two normal maps, and didn't solve primary problem. Am i doing it wrong?

tksuoran
07-20-2011, 09:52 AM
Did you also process bumpMap contents?

Nowhere-01
07-20-2011, 11:51 AM
No, what kind of processing do you mean? I thought, i can start with emulating compressing\decompressing process inside fragment shader to see if it helps.