Optimized EditableMesh Ocean Project

Don’t make it open source if you don’t want to, it is your creation after all. I’d like to see buoyancy tho, that would be really cool (I haven’t seen this done with custom oceans/bodies of water yet)

no i just plan to open source this as I haven’t seen many good-looking, modularized editablemesh oceans out there. i don’t have much use for it afterwards and I don’t really believe in gatekeeping software.

there have been a few implementations of these with skinned mesh oceans, so it shouldn’t be insanely hard to replicate.

3 Likes

this looks amazing. for client to client replication (i am not 100% sure i understand), couldnt you solve that by using a synced clock like workspace:GetServerTimeNow()? assuming ur talking about syncing the waves themselves. great job either way, if u do end up releasing this i will definitely be using it for a future game!

1 Like

Update


Managed to get the high-res endless mesh off the list.
Thanks to editable* being Objects now, I can replicate one editablemesh across several meshes. This allows me to tile them at lower vertex count but higher visual resolution (5x10 > 10x1).

Also cleaned up some stuff visually ontop of that.


Calmer waves:




More turbulent waves (wasn’t possible before due to low vertex count):



And some underwater caustics gobo that is in progress:


:wink:

5 Likes

Hey this is kind of irrelevant but for some reason when I try to create an EditableMesh and display it, it is invisible? Nothing is displayed at all… How did you pull it off? (Btw I’m using AddVertex and AddTriangles)

i mean it’s somewhat well explained within this thread but you have to use existingMesh:ApplyMesh(editableMeshPart).

my code for this ocean:

local existingWaterMesh = workspace:WaitForChild("water")
local AssetService = game:GetService("AssetService")

local editablemesh = AssetService:CreateEditableMeshAsync(existingWaterMesh.MeshContent, {FixedSize = false})

local meshpart = AssetService:CreateMeshPartAsync(Content.fromObject(editablemesh))

existingWaterMesh:ApplyMesh(meshpart)

existingWaterMesh being the meshpart already in the workspace.
idk it’s a been unintuitive but :man_shrugging:

I see. You are using an existing Mesh. Yeah that worked for me too, but making it from scratch doesn’t? I probably am missing something.

In my water system I’d like to add LOD functionality, which can require decreasing triangles with distance (though I can just use many different existing Meshes now that I think about it LOL)

Thanks a bunch for the help anyways.

yeah had a bit of trouble on that as well but pretty sure you can just do this to create one from scratch:

local AssetService = game:GetService("AssetService")

local editableMesh = AssetService:CreateEditableMesh()

local meshPart = AssetService:CreateMeshPartAsync(Content.fromObject(editableMesh)

would it not tank performance to generate waves for different meshes many times (e.g., 20x20 tiles)? I’ve personally been brainstorming ideas on this in terms of triangle count but to no avail just yet.

but anyways best of luck.

looks nice, only thing that’s missing are caustics on the terrain underwater and godrays from the surface but sadly this may be beyond roblox.

Well, because adding triangles won’t work for some absurd reason, my idea is to use existing MeshPart for the Water.

For the LOD (if you want my advice), simply divide the water into chunks. Why divide it in chunks?
Well, you see, you can make the One MeshPart only so large until you need to place another one, because the more you increase its size, the less detailed and smooth the water is, because there’s the same amount of triangles on more surface.

Contrary to what it seems like, dividing it into chunks with decreasing triangles each time is a great idea. This way less triangles are needed to render an ocean.
By welding everything to the Center Chunk and moving the Center Chunk along with the player (with something like BulkMoveTo or simple CFrames), you get a very performant water system!

yeah i did implement that the only issue is that my smooth brain screwed something up in my code and my gerstner waves aren’t seamless at the tiles.
using modulo makes it look odd at the seams so i need to find where i messed up… :sob:

Godrays are simulated with the Future Lighting Engine (under Lighting), and ONLY at max graphics.

There is a way to make Caustics on Terrain. But it is extremely difficult.

First of all they would have to be pseudo-caustics generated with EditableImage and something like Voronoi Noise.

Then, since we cannot display these on Terrain we would need to turn THE ENTIRE THING into an EditableMesh. This could be done at runtime, once, by raycasting on the Terrain multiple times in a square grid set off by a specific distance, so we could get the Vertex Positions of the MESH from the Terrain.
As you can already see, that’s BUSTED.
Hopefully there’s a way to actually edit the texture of Terrain, but I don’t think so.

Then we would need to Add the generated Color to the Corresponding Terrain Texture.
That gives us… a copy of the Terrain… just for Caustics.
It’s not worth it in the slightest.
It would be worth it if there was a single method to get these Vertices from the Terrain.

Seamless… you mean the chunks have empty spaces right? Yeah that was expected.
Yeah that’s why I originally approached a One Plane tactic. Would be good if roblox wasn’t so broken…

The only way to actually make this work is to go to Blender and individually split the faces… Man that sucks.

no by that i mean they’re not matching up at the seams.
i’ve thought about linear interpolation or something but the thing is i’m doing calculations for only a single tile and then duplicating the applied mesh. so not really an option and would look… eh.

That’s excactly what I meant. And it is NOT your fault. I am tryharding to fix this in Blender rn. There’s a little technique I can do to help with this.

Ah by the way did you use Planes or Cubes? because for some absurd reason when I try to animate Planes chaos emerges and everything dies. If you are using planes, please tell me so that I may also use them.

I probably did not recalculate normals haha.

planes. i could do cubes but that would add another layer of complexity and a bit useless for oceans unless roblox gave us alpha blending for editablemeshes.

for y = 0, scaledHeight do
	local row = {}
	for x = 0, scaledWidth do
		
		local xPos = (x / scaledWidth) * (width * 2) - (width)
		local yPos = (y / scaledHeight) * (height * 2) - (height)

		
		local vertexId = editablemesh:AddVertex(Vector3.new(xPos, 0, yPos))
		row[x] = vertexId

		
		verticepos[vertexId] = Vector3.new(xPos, 0, yPos)

		
		local colorId = editablemesh:AddColor(Color3.new(1, 1, 1), 1)
		vertexColors[vertexId] = colorId
	end
	vertices[y] = row
end

scaledWidth/scaledHeight being the width and height divided by a scalable resolution variable.
this is something I made just when editablemesh came out. it’s super bare bones (not to mention prone to bugs) but i don’t feel like changing it much unless you have some feedback

does it not already do this automatically as of the new api update anyways?

if you have anything to help with the seams it would be insanely appreciated :pray:

no but it is. the planes scale perfectly fine.
it’s just the fact that the gerstner wave height lookup function is being inputted completely different variables (e,g., -150 and 150 on tile edges) which won’t match up at seams if that makes sense.

i just need to rework the system a bit to be compatible with tiles.

FINALLY I DID IT


See what I’m talking about
I think I’m gonna subdivide some more wait.

1 Like


There that’s better.
Here’s the Blender file btw.
LOD.obj (313.7 KB)

I suck at blender so this took FOREVER to make…