Low poly water shader

Edit 2: Check out my newest version: Unipolywater shader

Edit: I’ve added a link to a downloadable version of the shader! Copying the code from this post does crazy stuff to the symbols..

The side tracking specialist strikes again.

I’ve been working on another project lately and ended up in need of low poly flat shaded animated water.

I tried editing the mesh at runtime by script. Using the method mentioned by joni.giuro here: http://forum.unity3d.com/threads/low-poly-water-help.276685/

But when using the standard plane with this script, basically 200 triangles and when you’ve separeted all vertices (600), FPS drops down from 1500 without script to 190 with script applied. If you add more planes or models with more triangles you quickly get to a point where you get 1 FPS. So I needed something else.

That’s when I figured I’d try my luck with shaders.

Tried googling for solutions, but nothing was to be found so I needed to build my own. With no experience in shader programming this proved to be harder than I expected. But fast forward through some horrible looking results to today. Now I’ve gotten to a point where I can take any plane (not having to worry about splitting verts) applying my shader and getting this:

Almost no hit on FPS with fully animated low poly flat shaded water with specular color. And with this solution:

I can add looots of planes with this shader with almost no hit on FPS. Here I’ve added got 30 standard Unity planes with 200 tris each, all animating off into the distance.

Here’s a video of it in motion:

So how is this done, you say?

Code below.

It’s not perfect but it works! F.ex. I’ve left the UV coords in there but don’t need them for this. And I’m not entirely happy with the waves just yet.. But here you go.

Link to downloadable version

46 thoughts on “Low poly water shader”

  1. Awesome work, i’ve tried myself to get my hands on shader, but it relatively dark when you don’t know about it in the first place.

    Really impressed, keep up the good work.

    Any chance that you do a kind of tutorial or a step by step guide on how to program such a shader ? (for newbs like me :D)


    1. This is my first shader, so I am relatively new to this stuff myself! I do agree that shader-information on the web is a dark place. Really hard to find good tutorials or clear answers to anything. But I finally managed to make this. But it’s a bit early for me to make a tutorial, and I don’t really have the time either.. Already found errors and weird behavior on this shader, but will continue working on it and might come back with more!

      1. I can totally understand that it’s very time consuming to do such a thing as a tutorial. Thank you for the reply though. 🙂

        By the way, i tried to download this shader to play a bit with it on Unity, and it won’t compile because of this error:

        “shader is not supported on this gpu (none of subshaders/fallbacks are suitable)”

        Ever came across this error ? I’m still searching for an answer on the web, and i can’t quite understand the problem there.

        If i manage to fix it, i’ll share it here 🙂

        1. If you are on Mac or some other platform than Windows without DX11 capabilities it probably won’t work.. It’s quite limited as is.. Unity will support geometry shaders on other platforms down the road I believe!

  2. Nice work! I tried a lot of times now to develope a low poly water shader by my own but I always give it up with the normal calculation. Can’t get it to work.

    Your shader is working but I get an offset from the pivotpoint of the object. It doesn’t render at the place I put my object.

  3. Nice work! I tried a lot of times now to develope a low poly water shader by my own but I always give it up with the normal calculation. Can’t get it to work.

    Your shader is working but I get an offset from the pivotpoint of the object.

    1. I believe the offset is due to scaling, not sure. Haven’t had time to look more into this shader. It could be improved in many ways!

  4. This is great!
    That low poly water look is exactly what i would like to have in my current project.
    I tried to use your example but i soon realized it isn’t affected by fog.

    I found this answer regarding fog in vertex shaders:

    However, with my limited knowledge about shaders i can’t figure out how to pass the fog data through the geometry function in your shader, so i can use it in the fragment function like in the example.

    Is there an easy way to achieve this?

    1. Hi, Brian! I really like your idea! And I hope you’ll get it working! The reason for what you are experiencing is a bug in the vertex function of the old shader. I’ve fixed it in my current shader, but not in the one I’ve shared.. I would have to spend some time on it to fix it, and I haven’t had free time to look at it. It’s a rather simple fix. Just have to change the way I added the offset of the vertexes. I believe I set v.vertex = mul((float3x3)_World2Object, v0) or something like that in the shader you have, but what you want is v.vertex.y += mul((float3x3)_World2Object, v0).y .. kind of.. But if you don’t know your way around shaders you could simply make a bigger plane in Blender and use that to get a bigger wave.

  5. This is a really cool shader. Can I use it for a commercial product? (working on a game that may or may not be published at some point). And another thing – by any chance did you think of adding reflection and transparency to it?

    1. Thank you! Yes! You can use what I’ve shared any way you want! I’m okay with that! I’ve already made a new shader with reflection and transparency, but I’m not sharing at the moment!

          1. I’m not sure I know what you mean, but if you are trying to get an object to “follow” the motion of the waves, you would either need to make another shader that displace the boat with the same wave code, or duplicate the wave code in script..

    1. Yes.. This is because the collider does not change! You need to duplicate the wave formula in code to make the boat follow.

  6. Hello Ronnie, this shader is awesome and just what I need!
    Though I would like to make the water semi transparrent, anyway to add alpha to this?

      1. Hmmm, it looks pretty nice and supports alpha, but it says it only works on DirectX 11 capable hardware, I’m planning on exporting to WebGL, so I don’t know if everyone would be able to play it, and after a little messing with the low poly water scene that comes with the package, I got a display driver stopped responding error and unity crashed 🙁

        1. Yes, my old shader is quite limited.. I’m not sharing my newest version yet, and don’t have time to support the old one.. I’m sorry..

          1. It’s ok 🙂 I can live with the non transparent one, thanks for making this free 😀

          2. No problem! Hope it works out fine! But fyi the non transparent one is also DX11 only i think!

  7. for people using more recent version of Unity :
    you must replace
    void geom(triangle v2g IN[3], inout TriangleStream triStream)
    void geom(triangle v2g IN[3], inout TriangleStream triStream)

      1. oh shame, that is a nice copy paste fail
        i meant :
        void geom(triangle v2g IN[3], inout TriangleStream triStream)
        instead of :
        void geom(triangle v2g IN[3], inout TriangleStream triStream)
        6 months too late …
        oddly, i have only been notified by your answer today.

        1. The reason your copy paste fails is due to the fact that this thing doesn’t except the chars you are pasting.. no worrys.. I think it is sorted if you use the link to the completed file.. it should be correct there.. 🙂

          1. ah yes, you’re right those little arrows still refuse to show up, and this time i’m sure i have not screwed up .
            I ve also seen that you added the missing output struct on the geometry shader on your new file indeed.
            I din’t realize that you were so active on answering questions on your blog, my attempt on helping out wasn’t even necessary !
            Nice work on all that by the way !

          2. Yeah.. It’s the same reason I had troubles with the code I shared on here the first time around! I’m not very good at posting on here, but I follow up on any questions that pops up! 😉 Thank you for the kind words!

  8. this shader looks like it would be perfect for a game i’m working on but it doesn’t work with the current version of unity 🙁

    1. Yeah.. I’ve abondoned this version of the shader.. I’ve redone the entire shader and have it working on newer versions og Unity, but it’s not public.. I’m sorry..

  9. Hi Ronnie!

    Thank you for sharing this shader. I want to use in my art project but i need an opaque version and i don’t find this parameter in the code. The alpha value is 1 but have some transparency. Can you help me, how can I modify the shader?

    Thanks in advance and sorry for bad English.

    1. Just change tags to «Queue»=«Geometry» and «RenderType»=«Opaque» . You can also remove the Blend line and the alpha parts.

      1. Hi,
        thanks for the fast answer. In the shader parameters the Render Queue already set to Geometrey, but I don’t find the Render Type parameter (Unity 2017.3.0f3). Btw removing the blend line in the code solved the problem.

        Thank you again and keep up the good work!

          1. I was maked a new shader and pasted your code. Thats all, but yeah, it is works. You will be credited 🙂

  10. Hello there, after tons of research I found this shader amazingly useful. Do you mind if I use this on my commercial game?

    Thanks in advance

    1. I don’t mind at all! The version I’ve put up here you may use as you wish! But keep in mind that it is not supported on all platforms!

  11. Hello. Thank you for posting this shader, it has really helped me understand how unity shader code works. In fact, I’ve written my own shader that is heavily based on yours (it’s mostly just the code handling specular reflection calculations that I’ve borrowed). Would it be alright if I potentially use it for commercial purposes?

  12. Hey Ronnie! Thank you so much for your amazing shaders. I wanted to have flat shaded low-poly cloth on my characters and as some people here already said – there is an unwanted offset.
    I know next to nothing about shaders but after some digging I changed this part of the code (which I suppose was essential for the wave effect, though):
    float3 v0 = v.vertex;
    v.vertex.xyz = v0;
    And it works perfectly! I hope this may help someone who’s looking for something similar 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *