Strange moire artifacts in specular

Hi,

I’m trying to add a simple specular effect to the water in a terrain model, and I’m experiencing some very strange artifacts. The following pictures show the effect.

http://www.worldbeside.com/screenshots/bug1.png
http://www.worldbeside.com/screenshots/bug2.png

As you can see it looks OK from a distance, but when zooming in, I get a shimmering sort of moire pattern in the specular highlight.

Here is the part of the fragment shader that calculates the specular. I’ve tried disabling everything else in the shader, and I’m pretty sure the problem lies in this code block somewhere:


       color.r = 49.0/255.0;
       color.g = 57.0/255.0;
       color.b = 82.0/255.0;

       vec3 ray = x0 - CameraPos;
       vec3 v = normalize(ray);
       vec3 n = normalize(x0);
       
       vec3 h = normalize(LightPos - v);
       float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0);
       float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0);
       vec3 sunLight = vec3(1.0, 1.0, 1.0);

       color += max(waterBrdf, 0.0) * sunLight * ISun;

Here x0 is the untransformed vertex position in geocentric xyz-coordinates, LightPos and CameraPos are given as uniforms in world coordinates. LightPos is normalized and directed towards the sun. ISun is a constant = 30.

I’m running this in Ubuntu linux 9.04 on a Dell XPS m1730 with 2x NVIDIA 8700M GT’s in SLI. Driver version 180.44 (linux).

Any ideas?

Cheers

Are you sure that at the end color is in the range [0,1]?

Yes, I added a


 color = clamp(color, 0.0, 1.0);

to the end to be sure, but to no effect.

Float precision issues ?
ie, if LightPos is very big compared to unit normal ?
10 millions to 1 is nearing the limit.

I was also thinking about float precision initially, since x0 and CameraPos can be quite big (a bit more than earth radius), but LightPos is given as a normalized direction vector, and all the other calculations in this part of the code are done on normalized vectors too, so I can’t really see why that should be a problem.

vec3 ray = x0 - CameraPos;

if x0 and CameraPos are large values, you’ll be dropping a LOT of precision here. Subtractions between large values of similar magnitude is deadly. See if you can get the ray direction in another way.

Ector, you’re right :slight_smile:

I just moved this calculation to the vertex shader (which made more sense anyway) and passed the ray as varying, and now the problem is gone.

Thanks for all help!