[SOLVED] Morphing geometry on shader level

Hi.

I’m thinking about improvement to my ‘die effect’, which you can see here.
What I want to do is to moph an existing geometry into a stain on the floor. I found where I should write the proper code and…that’s all, not enough math skill…

#import "Common/ShaderLib/Skinning.glsllib"

attribute vec3 inPosition;
attribute vec2 inTexCoord;
attribute vec3 inNormal;

uniform mat4 g_WorldViewProjectionMatrix;
uniform float m_FadeLevel;

varying vec2 texCoord;


void main()
{
    vec4 modelSpacePos = vec4(inPosition, 1.0);
    vec3 modelSpaceNorm = inNormal;
   
    #ifdef NUM_BONES
        Skinning_Compute(modelSpacePos, modelSpaceNorm);
    #endif
    
    //SOMEHOW modify modelSpacePos.xyz according to the value of
    //m_FadeLevel, which is between 0.0 and 1.0
    
    gl_Position = g_WorldViewProjectionMatrix * modelSpacePos;
    texCoord = inTexCoord;
}

Is here anyone able to do that, or at least give some hint? (“it is impossible”, “it won’t work” are hints too :slight_smile: )

Hello,
I would do it differently:
(1) You already have the modelSpacePos where it would be after bones (skinning) applied.
(2) You also have the position of the floor, which you need to transform to modelspace too.
(3) You have the time of death, in seconds, starting at zero.

I would simply simulate a falling particle:
``` height = max( height_start - (9.81f * 0.5f * time * time), floor_height)`

Remarks:
(2) if your dungeon has always the same “ground level” then you could give it as a constant to the shader

Edit: The floor will usually be at ``` y = 0 ` because your creature usually has root position at zero (where its feet are). For flying creatures like bats you might have an offset. I hope I’m right and y is up (not z).

I was trying with simple modelSpacePos.y *= (1.0 - m_FadeLevel) but it looks like scaling on only one axis. It looks bad.

improvement idea #1
And since you can calculate the time until particle hits the ground, you could make a “damped oscillation” (particle falls to the ground, bounces up a little, falls down again, … )

improvement idea #2
Also the stain might “flow” a little bit into x and z direction - so that the stain expands to left, right, forward, backward. I think that would look cool. simply take vec(position.x, 0, position.z) minus (0,0,0) and use a very small linear velocity in that direction (e.g. 0.03f meters per second or something like that)…

Yes, that’s why I would do it differently.
The falling particles will not have this problem.

Just simple physics (one of the few formulas that I remember from high school).

But how to populate the scene with particles that start their position on mob’s surface? The geometry should be the emitter, but I have hardware animations enabled, so as far as I know I don’t have the actual vertex positions on java level.
I’ll try that ‘flow’ idea.

No … not particles of a particle system.
I mean the vertex positions “as falling simulated particle”.
Will look like mesh falls to the ground (combined with dissolve shader should look cool).

I’m trying to modify the x and z coordinates while decreasing the y. Looks bad… maybe it is not a good idea at all…

Yes, do that after the vertices have hit the ground. Then it should look cool.
The time of hitting the floor can be computed by solving the formula that I posted.
Only bad thing: There will be a square root (sqrt) when solving it - but still cheap enough I gues…

Ok, I’ll try that tomorrow. Thank you.

idea #3
Let it form a small hill (like a cone with a very big angle) - might look like a small hill of ashes.
Might look bad or good, don’t know.
You will probably be small point above ground anyways, so:
height = max( height_start - (9.81f * 0.5f * time * time), floor_height + 0.01f )

Time of impact is as follows:
time = sqrt( ( height_start - floor_height ) * 0.2039f )

All my formulas assume that unit is “meters” (9.81 meters per second² is usually gravity G1 at ground level). So if you use a different scale, then you might simply multiply a factor to that.

Hm … I just thought about how that would actually look in a game. It would not look so cool.

I have ideas how to make it better, many ideas…
For example: Let the process begin at the outside of a “cylinder” and let that work slowly towards the central axis of that cylinder. So you calculate the distance of vec(pos.x, 0, pos.z) to (0,0,0) and…
Hm … too difficult to explain with pure text in a forum. :chimpanzee_sad:

I did it!
https://cdn.pbrd.co/images/1TvJYqEm.gif

4 Likes

Nice! :+1:

From thereon it’s probably just tweaking the visuals until it looks nicest in your view (e.g. change the speed of the stain getting bigger to different values or maybe let speed get smaller over time).

You could also try to implement improvement ideas #1 and #3 too.

And maybe this as improvement idea #4:

Of course I’ll try to tune it up. But I have the main effect I wanted yesterday.