WATER SIMULATION in Godot 4

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] lately I've been getting a bunch of people asking me to do a video on how to recreate the water ripple simulation Shader from my Unity boat game in Godot here's how I managed to do it as always links to resources are used will be in the description and so will any scripts you see in the video first let's recap the unity implementation to do the simulation we use a Unity feature called custom render texture this allows you to write a Shader that has its output rendered into a texture it also has a double buffer option which allows us to read the texture as we're writing to it this is important because the logic uses the previous state to calculate the next state speaking of which here's the simulation logic in the Shader I'm not going to pretend like I understand the maths or even know the algorithm being used I found it in this GitHub repo by a username takomi the resultant simulation state is stored in the r channel of the texture and the previous day is stored in the G channel for use in the next pass we can create a similar system in Godot using viewport textures in Godot create a new viewport smaller textures work better here as chunkier pixels make wider waves one thing to note though if you're following along in Godot 4.0 beta 3 there's a book currently where a sub viewport with a default size of 512 by 512 won't ever render you can fix this by setting it as any other size though unfortunately here I actually want to use 5tel by 512 so I'm going to set it to 514 by 514 instead after that add the child color Rec node to the viewport make sure the rect is set to fill the viewport by setting the layer anchor points to full rect on the color rect add a new shade of material and Shader foreign [Music] to recreate the double buffering of unity's custom render texture we just need to feed the viewport texture back into the color X Shader as a uniform now we need to recreate the Shader code using Unity Unity uses hlsl so we'll need to change some syntax but for the most part it's exactly the same as before float 2 and float3 become vect2 and vect free respectively text 2D becomes texture and that's about it if you're using Godot 4.0 beta you may have an issue with a viewport texture doesn't work correctly to get it working you just need to assign the texture to the Shader parameter via code like this if you're having this issue you're going to have to do this every time we use a viewport texture in any of our shaders going forwards to see the output let's create a plane mesh to represent our water [Music] give it some extra vertices by subdividing the mesh which will be useful for later here I've used some CSG nodes to build a wall around it and put in a plane for the floor too now on the water plane add a new visual Shader to it in our visual Shader take in our simulation viewport texture sample it and apply the r channel to our Albedo now that we have the simulation set up we just need to be able to feed it some Collision data or else nothing will happen in unity we set a camera under the water the camera will only render objects on a specific layer we set the output of this camera to a render texture and feed that into the Shader as a uniform we then attach a mesh to objects with a red color and set its layer to the same layer as the water camera if we set the far clipping plane of the camera to the level of the water anything it sees we can consider to be colliding with the water we can then sample the red value of the texture and apply it to the red value in our simulation this will then cause waves to form ingado is very similar and just as easy we'll do this using you guessed it another viewport texture create a new viewport and add a camera as a child set the camera projection type to author graphic and position it below the water make sure the size of the camera fits the size of the plane perfectly now pick a layer for the camera to render to I'm using 20 so I ensure the water camera can only see meshes on layer 20 and the main camera cannot see meshes on layer 20. in our simulation Shader set up a uniform for our Collision viewport texture and assign it in the Shader parameters because the camera is upside down we need to flip the yuv before sampling like so Now sample the Collision texture when updating our simulation we want to compare the previous Collision state to the current Collision State we can do this by storing the current Collision stay in the B channel of our simulation texture for the next pass we can Now sample the previous date from our simulation texture like so we can now update our simulation based on the Collision data when an object like a boat moves through the water the water in front of it is pushed out of the way and the water under the boat is pushed down we can recreate this using the previous and current Collision States here blue represents the previous Collision State and red represents the current Collision state what our logic is saying is if there is a collision where there wasn't one previously raise the water if there was a previous Collision where there isn't one now lower the water now we should be ready to start seeing some results we just have to run for a few setup steps and get an object to collide with our water first I just want to show the script that I've attached to main this is just to assign the textures to our shaders this is because as I mentioned previously Godot 4.0 Bayer has a bug where you have to set your viewport textures via script and this is what that looks like another thing I forgot to mention earlier is on your simulation viewport you have to ensure clear mode is set to next frame this is what lets the double buffering work then for our Collision object I've got a node 3D set up here which has a mesh which has a default material and it's set to be visible only on layer 1. and then I also have this water Collision which has a red material which is set to unshaded that's very important and it's set to layer 20. then I've got an animation player attached which just bounces the ball in and out of the water on a loop and if you run it we should see some waves [Music] now that we've got the simulation working let's sort out our water Shader go back to the visual Shader that we set up earlier where we just output in the red Channel and switch to the vertex tab start by sampling our simulation texture just like we did in the fragment Shader using the UV input and a texture 2D parameter I've had to set this up as another parameter because for some reason the new parameter reference node wasn't working add a float parameter called amplitude which will control how high the waves can go then multiply that by the red channel of our simulation texture then multiply that by the normal of our vertex finally add the results that previous logic to the input position of our vertex and then Plumb that into our vertex output we should see the vertices being raised up where the red is let's work on the fragment side now starting by reading from the depth buffer create an expression node then sample the depth texture and store it in a float the depth texture stores depth from a camera position to its far plane on a scale of 0 to 1. this is a logarithmic scale though and the value gets close to one very quick so we need to do some Transformations on it before it becomes useful to us if you're using Godot 3.x here you'll need to First transform this number to a scale of minus one to one we can do this by multiplying the number by 2 and subtracting 1. if you're using Godot 4.0 though you don't need to do this step as vulcan's normalize device coordinates on the z-axis are zero to one then we do some Arcane Wizardry with a projection Matrix to inverse a projection calculation of the depth value now if we add the result to the vertex a z value we get the distance between the surface of the water and the wall behind it if you put the result of this node into the Albedo you should see the depth visualized like so [Music] finally we should increase the murkiness of the water based on how long the light is traveling through it we can do that with a thing called Beer's Law we use the exponential method on the negative of our depth and multiply it by a float parameter so we can control how murky the water is if we reverse the output using a one minus node and plug it into the alpha Channel our water will now be more transparent the shallower the water is we can also use this to add some color variation to our pool create two color parameters one for shallow water and one for deep water then lurp these two colors together using a mix node and the depth result has our weight plug the result into our Albedo and we have color [Music] let's add some shade into our Waves by making our simulation output into a normal map create an expression node and use this code here that reads the simulations r Channel and converts it into a normal map then plug the result into the normal output [Music] finally let's add some refraction to the water based on the waves this is surprisingly simple take the normal output from earlier and multiply it by float parameter to control this effect strength add this value to the screen's UV and use it to sample the screen texture if you set this result to the Albedo it's easier to see what's going on here our water has become transparent because we're rendering the screen texture onto the plane but because of the normal offset when we create some waves you can see the view below the water gets subtly distorted just like in real life if we then mix this with our color we can get the final result foreign about with the parameters a little bit and adding some foam to the edges based on the depth buffer I got this result I added a capsule and a buoyancy script to it just to help move around and show you what happens when you move through the water as you can see from our collisions the water in front of the capsule is being raised to put the water behind the capsule is being lowered and also you can see the refraction taking effect as well the water will also bounce off of walls and just in general looks quite cool [Music] I think that'll do for this video if you found this video useful Please Subscribe and if you have any questions or suggestions for more tutorials please pop them in the comment section below but yeah cheers [Music]
Info
Channel: Crigz Vs Game Dev
Views: 114,755
Rating: undefined out of 5
Keywords: godot, godot 4, water simulation, shader, water shader, ripple shader, water ripple shader, glsl, hlsl, unity, unity3d, game, game dev, indie dev
Id: VSwVwIYEypY
Channel Id: undefined
Length: 11min 27sec (687 seconds)
Published: Sun Oct 23 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.