Mesh smearing

This tweet has been making the rounds lately:

https://twitter.com/popqjp/status/1658151081749405696

It shows a Blender shader that stretches parts of a mesh based on it’s motion. I would like to share my approach to recreating the effect inside of Godot 4.

Before reading on, I encourage you to try do it yourself without any hints!

 

Ready?

My approach is dead simple:

  • Define an additional transform which lags behind the current object, let’s call it the lag_transform
  • Interpolate between the transforms in the vertex shader

This way, it works naturally with any affine transformation (e.g. translation, rotation, scale). A parameter, t, determines exactly where the vertices land between their original position and the lagged position. As this happens on a per-vertex basis, noise can then be used to modulate the displacement over the surface of the mesh.

Tada!

 

See the final code below

GDScript

@tool
extends GeometryInstance3D

@export_range(0.0,16.0) var weight := 8.0

@onready var lag_transform := global_transform

func _process(delta):
	# lag_transform gradually approaches the current transform over time
	lag_transform = lag_transform.interpolate_with(global_transform, weight*delta)
	
	material_override.set_shader_parameter("lag_transform", lag_transform)
Shader code
shader_type spatial;

uniform sampler2D noise;
uniform mat4 lag_transform;

void vertex(){
	// a parameter determining magnitude of the displacement
	float t = pow(texture(noise, UV * 5.0).x, 6.5) * 2.0;
	
	// linearly interpolate between the current transform and the laggy transform in world space
	MODELVIEW_MATRIX = MODEL_MATRIX + (lag_transform - MODEL_MATRIX)*t;
	
	// puts it into view space
	MODELVIEW_MATRIX = VIEW_MATRIX * MODELVIEW_MATRIX;
}
Tags
displacement, smear, smear frame, stylized
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from celyk

Quick sky

Notes on the light function

Placeholder

Related shaders

mesh-terrain blending

Cube Mesh Glow Outline

UV and Normals Unwrap (Mesh Projection as UV) World Aligned

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
nasdv
nasdv
3 days ago

would it be possible to create a similar effect for 2d objects using the same approach? or do you think the differences between 2d an 3d transforms would get in the way?