Zi Profile picture
Jan 16, 2024 19 tweets 7 min read Read on X
Wanna make your own Wind Waker inspired ocean effect in Godot? Here's a quick and dirty guide!
#GodotEngine #gamedev
First, procure your ocean mesh(es). This can be a huge plane, or a disk, or many tiles. But it does need to be flat (y=0), and have enough subdivisions for you to see waves. The more subdivisions, the smoother the wave, so optimize for your needs.
Image
Image
Next: The foam texture! This is the SOUL of the effect, so spend time making it "you". Use a soft airbrush under a contrast adjustment layer. It gives clean edges while smoothing out sloppy brushwork. Feels satisfying, like molding clay.
This technique also makes it easier to fix edge discontinuities and make your texture seamless. Just apply an offset to your image, and paint your "repairs" over the discontinuities. They will automatically be smoothed out.
Now for some shadering! I'll show bits of code, but you can totally do this in a shader graph too. First, make sure you enable the render mode "world_vertex_coords". This lets us move or scale the ocean mesh (e.g. follow the player camera) without moving the effect itself.
In the vertex shader, pass VERTEX to the fragment shader via a world_pos varying. In the frag shader, use world_pos to build a UV to sample your foam texture (add a param to scale it to your liking). You now have a black and white ocean that stays fixed to the world.
Add two shader params for the water color and the light foam color, and reroute your previous foam texture sample to instead be a mix ratio between these colors. Now you should have a blue and white ocean pattern, or whatever colors you chose! Image
Add another shader param for the DARK foam color. In the frag shader, sample the foam texture a second time, with a (0.5, 0.5) offset from the light foam sample. Use this sample to do dark foam mix before you do a light foam mix. Now you should have two layers of foam! Image
The foam texture looks great at close and mid range, but far away, it looks busy and repetitive. We can calculate lateral-distance-from-camera in the vertex shader, pass it as a varying to the frag shader, and use it to fade away the foam. We can also expose params to adjust it.
If you made it this far, good time to mention that a huge part of the look of an ocean comes from its interplay with the sky, directional light, ambient light, and fog. Make sure to play around with these. I don't tend to use postprocessing effects, but you can add those too.
Next, create a distortion texture. This will be used to make the foam lines "ripple and wiggle". Combine a noisy red channel and noisy green channel. They represent motion along the X and Z axes, respectively. 128px is a good size for this.
You'll want to make sure your distortion texture matches the kind of distortion you want. Want big, sweeping line movements? Make a smooth texture. Want small ripples? Make a more noisy texture. Want both? Make your texture have big and small features.
In the frag shader, sample the distortion texture using world_pos. Take the sampled distortion value (R and G) and add it to the foam UVs from before. Make the strength and scale adjustable, but don't need to adjust them yet. Now you will have a distorted, static ocean! Yay!
Add a UV scroll to the sampling of the distortion texture (any direction works). Make the speed adjustable. Now you can easily adjust your distortion params because you can see the animation. You can use one distortion for both foams for performance, or use two for a nicer look.
We need a height function that tells how high the surface is at any point on the ocean. You can use any wave function you want (like a trochoid), but I chose to just average two sinusoids. For this, you'll need 4 shader params:
- speed
- frequency
- amplitude
Now just plug it into VERTEX.y in your vertex shader, and voila! Waves! Adjust the settings to your liking. We're almost there! But notice how the waves don't respect lighting - they just appear a uniform color no matter what. We need to give them normals that make sense.
In the vert shader, query the ocean height two more times - once a bit to the right, and once a bit forward. Take the cross product of the vectors formed by the three sampled surface positions, normalize it, and that is your new surface normal!
Now just throw in some pizzazz. Maybe make the waves dissipate far away from the camera, etc. If you need ocean surface gameplay logic (like buoyancy), you'll need to sync the ocean time by creating a global shader var. You can animate this in the editor using a tool script. Image
And that's it! Hope you have fun making this, and making it your own. 🐧🌊

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Zi

Zi Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(