0

I'm trying to write a simple shader that moves all verts with a sin wave.

v.vertex.y += sin(_Time.y * _Speed + v.vertex.x * _Amount * v.vertex.z) * _Distance;

The problem is that after moving them, the normals are wrong, thus there are no real time shadows. I've searched a lot and found that I need to recalculate the normals using fake neighbours. None of the implementations were for Unity Shaderlab, so I can't just copy and paste them, and my knowledge of shader code is pretty basic so I can't translate what I found to what I need.

Can anyone help me with what and how to recalculate normals after moving a vertex?

Al3x
  • 125
  • 2
  • 9

3 Answers3

1

The math behind normal calculation is cross product.

Take vertex A, B and C from a triangle. Then create vectors AB and AC. ABxAC will give you the normal of the triangle. ACxAB will give the opposite normal (ABxAC = - ACxAB).

en.wikipedia.org/wiki/Cross_product

If you were to move the mesh from Mesh class, there is a RecalculateNormals. But I guess that doesn't apply here as you work on the shader.

Everts
  • 10,408
  • 2
  • 34
  • 45
  • Exactly, the part I fail is creating these "fake" neighbours and then create these vectors to do the cross product. Luckily I was able to achieve a fair enough effect and ultra performant on mobile. What I did is to discard shadows altogether and created a simple texture. Now when the mesh moves the texture follows and now you can see it moving. It looks PRETTY GOOD and I don't have to deal with shadows (Since I'm targeting for mobile) – Al3x Dec 07 '17 at 02:25
  • The fake neighbours, I assume are the two vectors. When you get a triangle, it is made of three points, the vertices. It does not matter which you choose, it only matters that one vertex is the starting vertex of both vectors. – Everts Dec 07 '17 at 08:29
0

The normal vector of a surface is related to its derivative. In the case of a sinus wave its derivative is just cosine wave cos(). Both can be computed efficiently in a single operation called sincos().

Perfect introduction exercise :) plot both and observe the relationship.

The previous answer by Everts works when you have access to neighbouring vertices, which you usually don't in shaders (but that would be fine on the CPU).

Brice V.
  • 861
  • 4
  • 7
-1

Having not done this myself, I did a little googly and found this shader, used to invert the normals. It does this by tweaking the vertex information:

    void vert(inout appdata_full v) {
        v.normal.xyz = v.normal * -1;
    }

You should be able to tweak your shader to recompute the normal direction based off the other alterations and update it in a similar manner.