Finally finished up my approach at rendering an ocean, my method involves techniques used by games like sea of thieves and assassins creed black flag. They use what’s called the inverse fast fourier transform to convert their frequency domain over to the spatial domain, I opted to use this same one but mine uses a variation called the Radix-4 Stockham, it allows me to produce fft resolutions at power of 4, meaning 16x16, 64x64, 256x256 etc. This one you are seeing is at 64x64 as roblox meshes have a triangle limit of 10k meaning trying to go to 256x256 on the mesh is not possible (or 128x128 for that matter), since this is a limitation, the quality is also limited, but I did manage to use a workaround for the normal map, by using 120 generated normal maps that get cycled (these are at a resolution of 1024x1024 so they look really nice) this is the best I could get it to look, whilst also keep an eye on performance, on my pc which uses an rx7800x3d, 64gb of ram, and has a 5070ti, I can render it at around 1000fps, I know the metric isn’t very great, but it’s something I guess, anyway, here are some videos of it, I’d like to hear your thoughts on it.
how did you get the water to look like that? im not talking about the waves just purely the texture, i been trying to figure something out but no matter what i do the texture just looks like an image wrapped around it
im using EditableMeshes and SurfaceAppearance for my system, editing the UVs and normals of the vertices. are you also using an editable mesh or a skinned mesh? your said the normal map is generated, do you mean you are using an editable image for it?
So I’m using the same method you are using, an editable mesh + surface appearance. I don’t change any normals on the mesh itself as that’s being done strictly by the 120 generated normal maps, the normal maps are 120 decals all turned into editable images and stored inside of my code as strictly buffers, meaning no extra memory needs to be stored as the editable images themselves can be deleted, all we need are the buffers, for the surface appearance, I actually set the normal map property of the appearance to an editable image content so that I can change it in real time, and since every frame of the water texture is stored as a buffer, it takes little to no computation cost at all, I will admit storing 120 frames of 1024x1024 normal maps is not ideal for memory usage (taking up about 480mb, but for an entire ocean system that would presumably be where the entire game is player at, I think biting the bullet is more than fair).
You can download the same normal maps I used here:
so if im understanding this right, you upload the 120 normal map images as decals, store those ids somewhere, then at runtime convert the 120 normal map images into editable images, get the pixel buffer, destroy those editable images (doing this only once at startup), then create one more editable image for the surface appearance, then just do a simple animation to get the animated normal map. that helps me out a lot, thanks
though, do the UVs ever need to be edited/set?
and what about the actual setup of the mesh itself? you said you have 64x64 meshes does that mean 64x64 vertices on a 64x64 stud plane? and when you did your test were you doing the processing in parallel or serially? because 64x64 vertices across what looks to a lot of planes would require a lot of processing and doing that serially will definitely tank the fps
ok i got the normal maps in and i got them working but it takes about a minute and a half for it to create all the editable images, get the pixel buffer, destroy the image, store the pixel buffer so it can be used later and that would cause game load time to be very long. it works but how can i make the startup load time take less time
i first tried precomputing it and storing it as a string then decompiling it, but storing all of that created 600+ mbs of text in module scripts and caused the game to be unable to be saved
Yes, uv’s do need to be set if you are generating the editable mesh from scratch, if you are importing in a plane from blender or something it already comes with uv’s so you should be fine.
As for how the mesh works, the mesh actually tiles, so every single mesh that gets created actually all references a single editable mesh, meaning no matter how many mesh parts you have in studio, editing only a single editable mesh affects all of them at the same time, way better performance that way, this does mean that the ocean tiles, but everything in real time repeats eventually
and yes when I say 64x64 I mean vertices, although technically the plane is 65x65 in order to tile properly. Everything is also done sequentially, not in parallel.
this is also an issue I have encountered and I attempted to fix it the same way you have, the problem is that 1024x1024 images take up 4mb each, and storing them all in module scripts would take thousands of module scripts, which is just not something that’s possible, so the loads times are something NECESSARY, however you can skip the load time to make it work by instead rendering the ocean without textures immediately off of spawn, as the actual deformation of the mesh does not require the texture, you can then load the textures in parallel to the actual movement of the mesh, and begin rendering the textures as soon as they have all loaded, you can skip a loading screen as the ocean will exist instantly, but the full quality version will take time to load in, it’s just something that we have to bite the bullet on unfortunately.
it lowkey just renders SUPER far out, but you should also play with lighting properties as that’s also a huge factor, things like haze and whatnot help mask it if yours doesn’t render super far.