First WIP of scatter object displacement for MinerMancers. This will be for objects I don't want to destroy as you walk over / too near to them.

I'm using grass to test with for now simply because it's the easiest to make look OK - you can just flatten it and it looks fine. It'll get trickier for more substantial objects which will need to bend but not completely flatten - but the base principle is working at least

I'm not 100% sure I like this yet, but I'm trying to avoid having actual bones in these larger mushrooms and keep them in the instanced mesh. I don't want them to go pop like the smaller ones, and if I want them to bend out the way and animate properly I have to switch them for full skeletal meshes, and I really don't wanna. Push-aside is tough to look right with anything more complex than grass, so I give you: marshmallowy mushrooms that go flomp when you walk over them? 🤔
@sinbad You don’t want to try at least the simplest version of push aside you can think of (in shader, not bones) before deciding against it?
@runevision I already have that for grass and it didn’t look great for larger things. Might try some variations but the problem is the boundary. If you lerp it can fold and if you don’t it’s a hard edge. Only really works with very thin objects
@runevision you really need it to bend as a whole object and when something has lateral size you can’t do that on a vertex basis, it really needs a bone
@runevision hmm maybe I could use some per-instance data (2D position of the whole instance) and read that back in the shader…
@sinbad Yeah I was thinking using the 3D position of the instance. Then you’d be able to bend the object as a whole. I’ve done something tangentially similar for foliage lighting in the past, which required fake normals that knew of the object center.
@runevision yeah UE didn’t previously support per instance data (you had to pack everything into UVs or vertex colours) but looks like it does now, will dig into that tomorrow

@sinbad @runevision you could try a bend function that takes into account lateral displacement. Take a look at the opCheapBlend function at the end of this page. I imagine you’d remove the primitive parameter and return q instead. If you pass all vertices through it then they’ll be bent, the instance can have a transform you apply before displacement then inverse after to control the axis/offset it’s bent on:

https://iquilezles.org/articles/distfunctions/

@sinbad alternatively swap out the ones you want to bend with for a non-instanced one with bones. I don’t imagine it’ll be many
@bnut it’s more than you’d think, once you count multiple players and a few large NPCs. Thanks for the bend function, the problem remains that it’s not a centred calc. It a radius around a character and the transition from bend/notbend is tricky on a per vertex level. But I think per instance data can solve that

@sinbad yeah, the per instance transform I suggested should solve that (let you adjust the angle and amount). Rotate the transform for angle, scale the transform (on x) for the bend amount (may need a clamp), and translate the transform for where the bend starts.

Something like this:

```
out_vert = M_inv * opCheapBend(M * in_vert);

vec3 opCheapBend( in vec3 p )
{
float a = clamp(p.x, 0, 0.785);
float c = cos(a);
float s = sin(a);
mat2 m = mat2(c,-s,s,c);
return vec3(m*p.xy,p.z);
}
```

I think they’re pretty fast on modern GPUs, but if needed you can probably replace cos and sin with the first few terms of their Taylor series (because the bend amount will always be near zero).

@bnut thanks!

@sinbad no worries :)

A decent (untested) fast approximation of the blend will be something like:

vec3 opCheapBend( in vec3 p )
{
float a = clamp(p.x, 0, 0.785);
float c = 1.0-0.5*a*a;
float s = a;
mat2 m = mat2(c,-s,s,c);
return vec3(m*p.xy,p.z);
}

That’ll be fine for bending up to 45 degrees, which is where it’s clamped anyway. If you want more than that then I’d just combine a matrix with the inverse matrix to uniformly rotate it even further on its base.