Search code examples
glslvertex-shadernormals

Waving flag shader normals


I'm trying to create a vertex shader that produces a waving flag. I got the vertex positions going fine, but I'm having trouble adjusting the NORMALS to be what they should be in a waving flag. I did a little kludge, but it works from only SOME angles.

Here is the pertinent vertex shader code:

vec4 aPos=input_XYZ;
float aTime=(uniform_timer/75.)*7.; 
aPos.y+=sin(aTime)*.15f*input.XYZ.x; // The wave
output_XYZ=aPos*uniform_ComboMatrix; // Into scene space

vec4 aWorkNormal=input_Normal;
aWorkNormal.y+=sin(aTime)*.25f; // <-- Here's the kludge to inexpensively tip the normal into the "wave" pattern
output_Normal=aWorkNormal*uniform_NormalizedWorldMatrix; // Put into same space as the light's vector

So I want to lose the kludge and actually give it the correct normal for flag waving... what's the right way to transform/rotate a normal on a waving flag to point correctly after the y position is modifier by sin?


Solution

  • The transformation you apply to aPos is a linear one, which can be described by the matrix:

        [  1  0  0  ]
    M = [  C  1  0  ]
        [  0  0  1  ]
    
    C = sin(aTime)*0.15
    

    The normals then need to be transformed by the matrix W = transpose(inverse(M)):

        [  1 -C  0  ]
    W = [  0  1  0  ]
        [  0  0  1  ]
    

    Turning it back into code:

    vec4 aWorkNormal = input_Normal;
    aWorkNormal.x -= sin(aTime)*.15f*aWorkNormal.y;