Announcement

Collapse
No announcement yet.

Gerstner Wave Implementation - Am I doing this right?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Gerstner Wave Implementation - Am I doing this right?

    Edit: I just realized that maybe this would belong in the Programming section? If so, my apologies. I just saw materials be discussed in this subforum and thought this would be the place for it.

    Hey all. I'm currently building a small prototype, which unfortunately requires the use of a fairly realistic ocean. I've decided to try and tackle that scary-looking gerstner equation with a big specification, I want to try and control the direction and speed of the waves with a Wind actor placed in the level. That part was simple enough, and the equation looks fine in Material Editor*, but the effect looks... well, compared to the few examples I've seen on youtube, it looks almost nothing like it.

    * I'm fairly certain that I've messed up awfully somewhere here.

    Here's what it looks like, currently.
    [shot]http://gyazo.com/2be644b3cde658a3fc07bf0289139345.png[/shot]
    (the wave pans along whichever direction the wind actor is pointing)

    And here's what it should look like, in practice:


    If I understand the equation correctly, It's based off of adding more waves to achieve better results. Of course, this is me talking out of my butt, so I'm probably wrong, but assuming I'm correct, I've added more samples, and the only change is that I need to lower the amplitude to stop it from being so high.

    I'm a bit weary about releasing my material, but hey, it doesn't work anyway, so here's what it looks like with a single wave sample:

    [shot]http://gyazo.com/e7bed1bb961b73eccaedcf510357a428.png[/shot]

    That's plugged into the World position offset, I've just got a blue colour in the diffuse channel. As you can see, I've separated the material into material functions, to save on the clutter when I add the wave samples together.

    This is what the MF_GrestnerWave_Sigma_X material function looks like:

    [shot]http://gyazo.com/03d00fc11d5afbf0f2298aafc2d95ac6.png[/shot]

    The MF_GrestnerWave_Sigma_Y function is exactly the same except the Green channel is being pulled from the mask over the normalized wind vector.

    This is how the MF_GrestnerWave_Sigma_T function looks:

    [shot]http://gyazo.com/1de9330927fdc4652087a0f84ca2051a.png[/shot]

    That's the main functions. Here are how the others look at the moment:

    GerstnerWave_WaveFrequency_w
    [shot]http://gyazo.com/02d07e268c6519df5dcc8a8e28221aec.png[/shot]

    And finally, the MF_GerstnerWave_WaveSpeed_squigglyP (The phase-constant for the Wave Speed)
    [shot]http://gyazo.com/4726e9726d57dc385a69e97a4e13461c.png[/shot]

    For completions sake, this is the equation I've been using:
    [shot]http://http.developer.nvidia.com/GPUGems/elementLinks/013equ01.jpg[/shot]

    So yeah, if anyone would be kind enough to tell me exactly where I screwed up, it would be much appreciated. Thanks!
    Attached Files

    #2
    I'd say don't multiply x, y and t but append them to form a vector with 3 components.

    Comment


      #3
      That seems to have worked, in that I've now got a sine wave who's steepness I can control via Material Instance. Thank you for that! =]

      I'm just wondering, however, are those X's in the equation Multiplications, or Cross Products? If it's the latter, then I'm sure I have my Order of Operations screwed up, but, in my attempts to try and redo the equation, taking the cross products in mind, I seem to have killed the sine wave altogether.

      Comment


        #4
        Should be the cross product; there are "dot"-Multiplication operators in the equation as well: wiDi * (x,y) and so on...
        Can you show more of the results? It really sounds interesting what you did there! Haven't heard of something like that so far. Have to google this equation^^

        Comment


          #5
          Ah, well it looks like I'll need to completely redo the equation, it seems. I tried substituting in the cross products with the relevant multiplications, and it basically killed all movement in the waves.

          And it's been implemented in the UDK before, that video I posted above is rendered in UDK. Im just not a big fan of asking people to show me how to do it, I like to get my hands dirty (figuratively), even if it seems like I get in way over my head (if there's anything I'm not, it's a maths guy).

          Anyway, with how it looks at the moment, I'm afraid that it's not as exciting as that first image has lead you to believe, it's just a sine wave which I can "pinch" the top crest between a value of 0 and 1 (0 being regular sine-wave crest width, 1 being pinched), which is demonstrated in the gif below:

          [shot]https://dl.dropboxusercontent.com/u/29075670/GerstnerWave_01.gif[/shot]
          Give the gif a chance to load, it's over 20mb.

          It's subtle, but it's there.

          I've also got a gif (sorry about the gif's, I just cant be bothered with the whole video-capture-then-upload process at the present moment), demonstrating the control the wind actor gives me:

          [shot]https://dl.dropboxusercontent.com/u/29075670/GerstnerWave_02.gif[/shot]

          Sorry for the lower quality, the screen-to-gif capture program seems to have deleted my settings, not to worry, it still gets the point across. I can control wave-direction and speed using the WindDirectionalSource actor, which I find to be really cool.

          Anyway, I'll get to work on reimplementing the equation, and come back with some results... hopefully.

          Comment


            #6
            Hey, I'm still working on this material. Unfortunately, I can't post any pics in regards to the material itself because I'm currently using my internet's phone, and it's sketchy at even a basic internet connection, let alone uploading and all those fun things.

            I do have a few questions in regards to the material editor: Does anyone know how I can achieve a sigma function within the material editor itself? I've been wracking my brain over it, and I can't seem to get anywhere in regards to achieving it. So if anyone has done this (preferrably without the use of a custom shader node, because I've got no idea how to code HLSL), and can lend me a hand, it would be a great help.

            My other question is in regards to Order of Operations, and how it's handled in the UDK. Currently my material node has been "fixed" in regards to what I think the OOP is for the editor, but there's a very good chance that I've got it backwards. I'll try my best to include a picture of what I mean, but as it stands, my current material basically has no vertex displacement whatsoever.

            This is the current implementation of the SigmaX function.

            [shot]http://gyazo.com/4feeb75f4b7b5cb2bd7c3174c5ffe2a1.png[/shot]

            The Wave Frequency and Wave Speed functions have not changed from the top picture, and the SigmaY implementation is exactly the same except there's a cross product of the Wind's direction in the G component, instead of R. (Also don't mind the connections off screen, they just connect to inputs on the old implementation, which is not connected at this moment.)

            It all looks fine to me, but there's no movement of my plane at all when the changes are applied. So if anyone can help in regards to my questions above, it would be greatly appreciated.

            Comment


              #7
              Can no one help? Sorry for harping on this, but I'm just wracking my brain on this issue, nothing I'm trying seems to bring any movement at all.

              Comment


                #8
                I've been meaning to take a deeper look at this, but I haven't had the time. Maybe over the weekend, no promises.

                A couple of things that struck me after a quick google. Firstly, this is only one wave. The algorithm is a summation of several waves, and I suspect you need ~4 sets of these, like harmonics, to produce the actual result. The Gerstner wave is a single sinusoidal wave that pulls vertices in toward the peaks, causing sharpening.

                Secondly, and I find this confusing, the formula does look like cross product notation - yet the two code samples I found online just use multiplication.

                So... what you had before the cross products may actually be correct. Maybe. Don't quote me on that

                Comment


                  #9
                  The Cosine wave doesn't move in preview? Then the problem must be the MF_GerstnerWave_WaveSpeed_squigglyP.
                  If it outputs 0, so that the time node has no chance to move anything around. That's where I'd look first.
                  If I understoond your problem right.

                  Comment


                    #10
                    I've prototyped it using the sum of just two waves and already I'm getting interesting results, so you're original setup (after changing from multiply to append vector) is correct. The cross product notation seems to be a red herring, the arguments are scalars so I can't see how it would fit in, though I'm no math expert.

                    As I said, a single Gerstner wave is just a sine wave with sharpened peaks, and the gifs you posted are similar to my results.

                    Actual ocean motion (I like the sound of that) only emerges when you start layering multiple waves together. The GPUGEMS article suggests 4 waves, beyond that it needs to be replicated in the pixel shader to produce fine grain and detail in the normal map. My vertex-only test is causing nasty artifacts with shadowing (edit: actually it's the lighting, which the normal map should resolve).

                    Comment


                      #11
                      Originally posted by Spoof View Post
                      I've prototyped it using the sum of just two waves and already I'm getting interesting results, so you're original setup (after changing from multiply to append vector) is correct. The cross product notation seems to be a red herring, the arguments are scalars so I can't see how it would fit in, though I'm no math expert.

                      As I said, a single Gerstner wave is just a sine wave with sharpened peaks, and the gifs you posted are similar to my results.

                      Actual ocean motion (I like the sound of that) only emerges when you start layering multiple waves together. The GPUGEMS article suggests 4 waves, beyond that it needs to be replicated in the pixel shader to produce fine grain and detail in the normal map. My vertex-only test is causing nasty artifacts with shadowing (edit: actually it's the lighting, which the normal map should resolve).
                      Oh wow, thanks for taking time looking into this for me! You know, I had a feeling that my original implementation (with the appends, and not the multiply's), as shown in the gif was correct, since it produced the exact results described in my research, I guess I was fooled by the cross product notation, and was actually just coming to this topic to discuss how weird it seemed that there would be a need for Cross Products on Scalar components, which is probably why there was no movement in the new implementation in the first place. Though it's a massive relief to hear that I was on the right track to getting an ocean up and running, despite being pulled off course by the siren known as Cross-Product Notation.

                      If I may, how did you manage to layer multiple waves together? Is it just through a multiply node? Add?

                      The replication to a pixel shader sounds like a difficult task, but one I'm more than happy to take on when I'm done with this problem in particular... though I am wondering if I can cheat and just combine it with the OceanShader tutorial I mentioned above It's also odd that it can only theoretically support 4 waves, because the author of the video I posted above boasts 35-40. Oh well, I'll cross that bridge when I get to it.

                      Ocean motion is indeed an awesome term! And thank you, again!

                      Comment


                        #12
                        Combine waves by adding their results and dividing by the total waves.

                        You can have a lot more waves, the Clear Sailing demo (scroll down) used 45 waves. The original article in your post, which predates Clear Sailing, uses 4 waves because it fits into a convenient shader optimisation pattern: the scalar properties for all four waves are passed through a Vector4, requiring only one instruction to multiply them in one go. So there are no iterations in their implementation, all four waves are automatically processed and summed in one go.

                        In my test the instruction count almost doubled with two waves, but all I did was add in a second material function with parameters. I don't know how effectively the material editor optimises nested material functions, but to get a lot more waves using the node editor you may have to rethink the structure to add some manual optimisations such as packing Vec4's. You can gleam some extra insight by downloading the demo code and checking out WaterRipple.fx

                        The OceanShader tutorial will probably guide you through the pixel pipeline, and you can then correlate that with the rest of the NVidia article.

                        Comment

                        Working...
                        X