I just did something like this - trying to make deforming surface waves in an ocean shader. This worked out pretty well for a basic wave – but it assumes there’s only vertical, Up-wards displacement. It’s all happening in the Vertex shader, so even though it’s inefficient, at least it’s not per-pixel…
I wouldn’t use this in a complicated environment, but for illustrative purposes:
float getDisplacement( float4 UV )
{
float4 data = tex2Dlod(targetSampler, float4( UV.xy, 0, 0));
float disp = data.g;
return disp;
}
#define numPixels 128
#define uvStep 1.0f / 128
float4 getNormal( float4 UV )
{
float tl = getDisplacement( UV + uvStep * float4( 1, -1, 0, 0 ) );
float l = getDisplacement( UV + uvStep * float4( 1, 0, 0, 0 ) );
float bl = getDisplacement( UV + uvStep * float4( 1, 1, 0, 0 ) );
float t = getDisplacement( UV + uvStep * float4( 0, -1, 0, 0 ) );
float b = getDisplacement( UV + uvStep * float4( 0, 1, 0, 0 ) );
float tr = getDisplacement( UV + uvStep * float4(-1, -1, 0, 0 ) );
float r = getDisplacement( UV + uvStep * float4(-1, 0, 0, 0 ) );
float br = getDisplacement( UV + uvStep * float4(-1, 1, 0, 0 ) );
float dx = tr + 2*r + br - tl - 2*l - bl;
float dy = bl + 2*b + br - tl - 2*t - tr;
float normalStr = 0.5;
float4 N = float4( normalize( float3(dx, 1.0 / normalStr, dy) ), 1.0);
return N; //* 0.5 + 0.5;
}
Disclaimer - I did grab the technique from a paper on the 'net about calculating normals from heightmaps. I can’t find it, and I’ve forgotten the link, and I feel awful about it. So – I can’t take credit for the algorithm. If I find it I’ll edit this post with the info.
But, I did get it working in FXComposer and in the Max viewport.
>> Edit >>
Ah, I read about it from Catalan Zima’s Height -> Normals article, located here:
http://catalinzima.spaces.live.com/blog/cns!3D9ECAE1F2DC56EF!223.entry
It’s called the Sobel filter.
<< End Edit>>
~