Definitely a bug. Your vertexSpacing value is incorrect. It needs to be the actual vertex spacing at each LOD, otherwise the normal will not be built correctly.
float3 normal = normalize(float3(dx, dy, 2*vertexSpacing))
Vertex spacing should go as a function of LOD as such:
vertexSpacing = spacingAtLODZero / (LOD ^ 2)
Where LOD starts at 0 (largest patches) and increases from there. In other words, vertex spacing should decrease by half each LOD.
This explains your image. By not decreasing vertexSpacing at each LOD, the vertical component of your normal vector becomes relatively larger and larger than what it should be, compared to the scale of the horizontal components. If you were to depict your normals visually, I bet theyâd all be pointing straight up (or close to it). Do you have the appearance of a strong âspecularâ effect (almost like reflective) when you look straight down at the surface?
@zameran Hereâs how I calculate my normals:
[The following two shaders are dispatched with thread group sizes of (1, 1, 1) (although eventually this will change)]
First stage, generation of vertex positions:
#define nVertsPerSideWithBorder 130
[numthreads(nVertsPerSideWithBorder , nVertsPerSideWithBorder , 1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
int outBuffOffset = id.x + id.y * nVertsPerSideWithBorder;
//generate height value, i.e.
float height = amplitude*sin(frequency*TWO_PI*(id.x - offsetX)/(float)nVertsPerSideWithBorder );
...
positionsOutput[outBuffOffset].pos = float4(id.x*spacing, id.y*spacing, height, 1);
}
Second stage, generation of normals:
#define nVertsPerSideWithBorder 130
#define nVertsPerSide 128
[numthreads(nVertsPerSide , nVertsPerSide , 1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
int inBuffOffset = (id.x + 1) + (id.y+1) * nVertsPerSideWithBorder; //'input' index of positions buffer
int outBuffOffset = id.x + id.y * nVertsPerSideWithBorder; //'output' index of vertexBuffer
float n = positionsInput[inBuffOffset + nVertsPerSideWithBorder].z;
float s = positionsInput[inBuffOffset - nVertsPerSideWithBorder].z;
float e = positionsInput[inBuffOffset + 1].z;
float w = positionsInput[inBuffOffset - 1].z;
float ew = e-w;
float ns = n-s;
float3 result = normalize(ew, ns, 2*spacing);
vertexOutput[outBuffOffset].normal = result; //store normals in 128x128 output buffer
vertexOutput[outBuffOffset].position = positionsInput[inBuffOffset].pos; //copy vertex positions from 130x130 input buffer to 128x128 output buffer
}
I hope that helps!