How to make convincing top down 2D water / beaches

edited in Questions and Answers

Does anyone have ideas for making nice top-down 2D water? For Grave Days, my outside terrain is generated from overlapping flat meshes. In the attached image you can see what I mean. I've got a huge, flat, grass textured mesh on the layer below, and another texture mesh slightly above it for the path - so I can generate these on level load which is what I am after.


Currently my world is constrained by blackness / the void - with nothing happening at the edges. I'd like to perhaps generate some ocean or something around to make it feel like you are trapped on an island. If this seems too challenging I might just go for something else. Any ideas though on techniques to get this right? I think I should be able to get some decent waves and shimmer in a fragment shader but how do I handle the boundaries between the water and the beach? Currently at best I'll be able to get a hard edge between the water and the beach like I do with my road and the grass. Should I rethink my approach of using meshes to generate terrain geometry?

Something that looks like this would be beyond awesome:
1920 x 1080 - 839K
Thanked by 1Tuism


  • I've started working on the water. I've seen switched to a tile-based set-up instead of using meshes. Makes procedural gen a bit simpler for me. Still need to handle the edges of the water but I think I have an idea for that now. So far pretty happy with the progress of the water but there's still a few tricks I can try.

    If anyone has any shader suggestions here I'm all ears.

    678 x 455 - 757K
    Thanked by 3critic konman Jurgen
  • That looks really cool! I think you could do some work on the colors, maybe changing color the closer it is to land.
    Thanked by 1Denzil
  • @roguecode Thanks! Trying that now, kinda struggling to get the waves to go towards land. I suppose I could just also add a static colour gradient based on "depth". I guess this is what you meant, but I also want to add some shading to the waves, but then the direction of the waves become extra important. It looks pretty stupid if the waves travel from the shore outwards into the ocean. I think I'll part this for now, but I'll definitely revisit your idea in the future.


    The last change I've added was to add some edges to the water that overlap onto the sand. Not 100% happy with it. Not sure if it looks better with or without it. Thinking of trying some different sprites that might look better than what I have now.
    792 x 509 - 7M
  • edited
    I've been working on a similar problem, using GLSL shaders.
    I came up with a solution that will auto-create ocean based on terrain colors.

    The beach and waves are calculated using statistics function that generates a bell curve:
    float NORMDIST(float x, float mean, float standard_dev)
    	float fact = standard_dev * sqrt(2.0 * 3.1415);
    	float expo = (x - mean) * (x - mean) / (2.0 * standard_dev * standard_dev);	
    	return exp(-expo) / fact;

    where x = the 'blueness' of the texture

    in GLSL:
    //satimage is the satellite image
    vec3 originalcolor = texture(satimage, fs_in.TexCoords * TexCoordScale).rgb;
    //oceanmaterial is a texture of ocean waves [img][/img]
    //sample at different resolutions for mixing
    vec3 color2 = texture(oceanmaterial, fs_in.TexCoords * Tex2CoordScale * 50.15).rgb;
    vec3 color3 = texture(oceanmaterial, fs_in.TexCoords * Tex2CoordScale * 220.15 + sin(iTime*0.15)).rgb;
    //calculate blueness of the fragment on the satellite image
    float blueness = (originalcolor.b - originalcolor.r) + (originalcolor.b - originalcolor.g);
    float f1 = NORMDIST(blueness, 0.1, 0.03 );
    color += f1 * 0.45;
    //major wave
    color += color2 * NORMDIST(blueness, pos, 0.06 + sin(iTime*0.5)*0.02) * 0.040;
    color += color3 * NORMDIST(blueness, pos - 0.06, 0.01 + sin(iTime*0.5)*0.0001)*0.015 * FogMultiplier;
    color = mix(color,	color2, blueness);

    The transparency between wave and sand underneath is entirely an optical illusion generated by the lovely NORMDIST function.

    Here's a video of the (still not perfect, but getting there) result (colours exaggerated for effect):

    Thanked by 1Denzil
  • Thanks for sharing! Great work. I'll see if there's some ideas I can use here when I come back to this.
Sign In or Register to comment.