I'm following the J. Tessendorf paper "Simulating Ocean Water", I managed to get the heightmap and the normal map using the finite difference method but I struggle to use these normals.
As far as I understand, these normals are in tangent space thus I need a way to convert them to world space for lighting calculation. The problem is, I'm not sure how to generate the TBN matrix which will allow me to transform the normals.
I tried Normal Mapping Without Precomputed Tangents but I have been unsuccessful, I'm not sure it can be applied here.
I don't really know what to try next, I'm using a plan deformed in a vertex shader, so the TBN cannot really be computed on CPU, anyway it would have been slow to compute it every frame as the water change.
In the paper the author suggests to use another iFFT to compute the slope vector (not sure of what a slope vector is, compared to tangent/bitangent) and then give a formula to get the normal (eq. 36 in the paper). I'm pretty sure these normals come in tangent space too.
Could you help me to transform these normals in world space ? Should I use the finite difference method, or use another iFFT to get the normals ?
Here is what I have now so you can check how I compute my normals and use them (cg shader). i'm using unity and _WorldSpaceCameraPos is a builtin shader variable with the position of the camera in world space.
vertex shader :
v2f vert(appdata_full v) {
v2f o;
float3 D = tex2Dlod(_MainTex, float4(v.texcoord.xy, 0, 0));
//128.0 hard coded to be sure it's working, I'm using 128x128 textures
float3 off = float3(-1.0 / 128.0, 0.0, 1.0 / 128.0);
float s11 = D.x;
float s01 = height(texcoord + off.xyyy);
float s21 = height(texcoord + off.zyyy);
float s10 = height(texcoord + off.yxyy);
float s12 = height(texcoord + off.yzyy);
float3 va = normalize(float3(2, 0, s21 - s01));
float3 vb = normalize(float3(0, 2, s12 - s10));
float4 bump = float4(cross(va, vb), s11);
o.pos = mul(UNITY_MATRIX_MVP, (float4(v.vertex.x + D.x, v.vertex.y + D.y, v.vertex.z + D.z, 1.0)));
o.color = float4(bump.xyz * 0.5 + 0.5, bump.w);
o.texcoord = v.texcoord.xy;
o.viewVector = _WorldSpaceCameraPos - o.pos.xyz;
return o;
}
fragment shader :
fixed4 frag(v2f i) : COLOR {
float4 N = i.color * 2.0 - 1.0;
float3x3 tbn = cotangent_frame(N.xyz, -i.viewVector, i.texcoord);
N.xyz = normalize(mul(tbn, N.xyz));
return float4(N.xyz * 0.5 + 0.5, 1.0);
}
cotangent_frame function is from the article, i'm just trying to visualize my normal in world space but all I get is blue normals.
The code in the vertex shader to get the normal from the heightmap is from this post