0

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

Community
  • 1
  • 1
  • Shouldn't you sample the height map in the fragment shader? Otherwise, you will be limited by the density of the vertices on the plane. And shouldn't the tangent plane of water just be the xy or xz plane? Converting to world space is trivial and usually just involves switching the axes. Also, I don't see why you need to encode the normal like this when passing it from the vertex shader to the fragment shader. And why do you use 4D texture coordinates (`off.xyyy`)? – Nico Schertler Oct 20 '16 at 22:20
  • I'm sampling the heightmap in the vertex shader because I need to change the vertices height there. I don't know if I can compute my normals in the fragment shader but I think that anyway, my normal must reflect my deformed planed, and the interpolated values would be fine. For the tangent plane, I don't know if it must be the tangent on my flat plane, or after it has been deformed. As for the normal encoding, I'm using CG shader and the normal is 'float4 normal : COLOR' . I can't find any doc on the COLOR semantic so I assumed it wants a value between 0-1 but I might be wrong ! – Alexis Girard Oct 21 '16 at 08:15
  • Semantics are just used to match the variables to each other. Except from the system value semantics, they do not imply any specific type. If your height map is over the undeformed plane, then so are your tangents. But you don't need tangents to just switch the normal's axes. – Nico Schertler Oct 21 '16 at 12:14
  • So you are saying that if my plane is axis aligned with my world, my normals are automatically world space ? Thanks for your help ! – Alexis Girard Oct 21 '16 at 13:01
  • Yes, that's what I'm saying. – Nico Schertler Oct 21 '16 at 13:32
  • Thanks for your help, got it ! It makes sense, if that was an answer I would definitely accept it. – Alexis Girard Oct 21 '16 at 13:37

0 Answers0