Godot vertex shader to bend a mesh along a path (similar to the Blender's "Curve" modifier)

364 views Asked by At

Similar question: Bend a mesh along spline

Related: How to bend geometry with geometry nodes

Related: Unity Curve Modifier


What I'm trying to do:

I want to create a Godot vertex shader that bends meshes along a Path3D similar to how the "Curve" modifier works in Blender.

Here's an example of that:


What I have done so far:

I've made this shader.

void vertex() {
    vec3 vertex_norm = vec3(
        VERTEX.x / curve_length,
        VERTEX.y / curve_length,
        VERTEX.z / curve_length
    );

    vec3 curve_position = texture(positions, vec2(vertex_norm.y, 0.0)).xyz;
    vec3 curve_normal = texture(normals, vec2(vertex_norm.y, 0.0)).xyz;
    vec3 curve_binormal = texture(binormals, vec2(vertex_norm.y, 0.0)).xyz;

    curve_normal *= VERTEX.z;
    curve_binormal *= VERTEX.x;

    vec3 offset = curve_normal + curve_binormal;

    VERTEX = curve_position + offset;
}

Here's how it works behind the scenes:

  1. The curve is obtained from the Path3D and is sampled for a predefined amount of times. (in a for loop)
  2. For each sample curve.sample_baked_with_rotation(offset) is called, giving us positions, normals and binormals of each sample of the curve.
  3. Three FORMAT_RGBF Images are created - each contains positions, normals and binormals encoded in rgb values. The width of the textures is an amount of samples and the height is 1px.
    • For example, if we use 128 samples, the width of images is 128px.
  4. These images are then converted into ImageTextures and are passed to the shader together with a total length of the curve. (the curve_length variable)

What doesn't work:

Broken vertices — SOLVED, SEE A COMMENT
Some vertices do this weird thing, I'm not sure how to describe it exactly. I thought that maybe this happens because of the negative y values, but I'm not sure.
I've tried clamping the y coordinate of vertices to (0.0, 1.0) but it didn't help.
Direction of the curve breaks the shading (need to recalculate the normals)
I need to recalculate the normals after the displacement is done, but I can't figure out how.

So the question is…

How do I fix these issues and make this Godot shader behave just like the "Curve" modifier from Blender?


Additionally, is it possible to make it so that the mesh is never truncated if the curve is shorter than the mesh? (see the screenshots below)

The curve is longer than the mesh The curve is shorter than the mesh, but the mesh is not truncated

Thanks!

1

There are 1 answers

0
Biggles On

It looks to me like the example video uses some "special case" logic at the base of the mesh, adding vertices to the side that's "stretched" on the outside of the bend & only "clamping" the vertices on the "compressed" side up to a certain angle, after which they are allowed to "go negative" below the base (though notice that at extreme angles there is a bit of curvature to that side of the base of the mesh)

I'm guessing that Blender's Curve modifier has no issues with adding additional vertices there, though a vertex shader might?

For the second question, is this not simply a case of scaling curve_position.y by mesh_length / curve_length? I guess you'd need to calculate mesh_length outside of the shader & pass it in though...