The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates.

godotengine.org | Twitter

+1 vote

I'm making a sea with waves and buoyancy

I've got running a shader that modifies vertices height so I've got a visual sea going on, but I have trouble getting the vertices height to implement buoyancy. That's the only parameter I need to succeed. I'm using a shader material in a PlaneMesh that I've subdivided.

My sea level is not constant because It's got waves so I can't use y=0 as reference. I've tried 3 aproaches unsuccessfully thus far:

-Trying to get the height back from a shader -> Turns out you can only get uniform params and those can't be modified inside the shader as far as I know

-Using MeshDataTool to access the vertices -> Somehow even if the shader modifies the vertices, they all keep their y=0 when I access them via MeshDataTool, I've tried creating a new MeshDataTool every frame too

    Samplecode:
extends MeshInstance
    (...)
var surface_tool = SurfaceTool.new()
var mesh_data_tool = MeshDataTool.new()
surface_tool.create_from(mesh,0)
var array_mesh = surface_tool.commit()
mesh_data_tool.create_from_surface(array_mesh,0)

-Generating a collider with createtrimeshcollision() and createconvexcollision() -> The resulting collider is always a plane, no waves to be touched. Maybe it could be a way to generate a collider from vertices? Either way I haven't found either the way to do that nor the way to get those vertices correctly

It is absolutely needed for the final result to be a sea in movement in which is possible to sample the varying height at any point, if you have any suggestions in the way of achieving that it would be most welcome

Thanks in advance

Godot version 3.2.3
in Engine by (15 points)

Update:
I made it work as intended by modifying geometry in CPU instead of the GPU. I figured shaders don't make permanent changes. It is however noticeably slower, maybe I can apralelize it but I doubt the scalability of this solution, the best case scenario remains somehow getting the output of a shader. Maybe I could do it with a texture but I don't know how to do that

Here the code until now:

func apply_sea(delta):
var time_now = OS.get_ticks_msec()
var time = time_now - time_start
surface_tool.create_from(mesh,0)
var array_mesh = surface_tool.commit()
mesh_data_tool.create_from_surface(array_mesh,0)

for i in range(mesh_data_tool.get_vertex_count()):
    var v = mesh_data_tool.get_vertex(i)
    var f1 = amplitude.x * sin(v.x * frequency.x + time * time_factor.x)
    var f2 = amplitude.y * sin(v.y * frequency.y + time * time_factor.y)
    var height = f1 + f2
    v.y = height
    mesh_data_tool.set_vertex(i,v)

for i in range(array_mesh.get_surface_count()):
    array_mesh.surface_remove(i)

mesh_data_tool.commit_to_surface(array_mesh)
surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
surface_tool.create_from(array_mesh,0)
surface_tool.generate_normals()
mesh = surface_tool.commit()
mesh.surface_set_material(0,material_shader)

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.