Depth based Tilt-shift
Updated to 4.3 (look at comment regarding POSITION in vertex() for lower versions)
Tilt-shift is an effect that blurs out parts of the image far from the plane of focus, creating a miniaturization effect. You can fake this effect by just blurring out top and bottom of the screen, but this fails if you want to: focus on a tall object that overlaps the blurred parts of the image, when camera is looking top-down (blur based on height), and if left right parts of image should be blurred (when going through a canyon).
This doc explains focal planes: Tilt Shifting and Focal Planes
This shader is a screen shader that reads depth from a quad applied over the camera. You will need to follow instructions from godot docs on how to set up one: Full screen quad
If your camera moves, you will also need to update the focal point of the shader through code, either to follow your moving object or where camera is pointing:
func _process(delta):
mesh_instance_3d.mesh.material.set_shader_parameter(&"focal_point", global_position)
Note: Doesn’t blur objects with transparency, but this is an engine issue
Models from KayKit-City-Builder-Bits-1.0
Shader code
shader_type spatial;
render_mode unshaded;
uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
varying mat4 CAMERA;
/** Focal point of camera in world space
* Change this in code to follow where camera is looking at, or follow player position
*/
uniform vec3 focal_point = vec3(0.0);
/** Depth of field, the width of focal plane in meters
*/
uniform float DoF = 5.0;
/** Maximum amount of blur based off of distance from focal plane
*/
uniform float blur_cap: hint_range(0.0,8.0) = 2.0;
/** How quickly blur occurs away from focal plane
* Bigger number is slower, smaller number is faster
*/
uniform float blur_rate = 2.0;
/** Multiples y vector of focal plane to make it less or more vertical
* Value of 1.0 is no change (focal plane is perpendicular to camera), 0.0 will make focal plane vertical regardless of camera angle (perpendicular to floor since y vector is now 0).
* Focal plane is typically perpendicular to camera view, but a more vertical focal plane may sometimes look better if we want background to blur consistently regardless of distance to plane.
* Example use case: Tall buildings show up focused in background because they are at same depth as focal plane, and while this is correct we may not personally like the look so we set value closer to 0.0.
*/
uniform float vertical_bias = 1.0;
void vertex() {
//4.2 and lower
//POSITION = vec4(VERTEX, 1.0);
//
//4.3 and higher
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
//
CAMERA = INV_VIEW_MATRIX;
}
float PlanePointDist(vec3 pn, vec3 pp, vec3 p){
float d = -(pn.x * pp.x + pn.y * pp.y + pn.z * pp.z);
float a = abs((pn.x * p.x + pn.y * p.y + pn.z * p.z + d));
float b = sqrt(pn.x * pn.x + pn.y * pn.y + pn.z * pn.z);
return a/b;
}
void fragment() {
float depth = textureLod(depth_texture, SCREEN_UV, 0.0).r;
vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
vec4 world = CAMERA * upos;
vec3 world_position = world.xyz / world.w;
vec3 focal_plane_normal = focal_point - CAMERA_POSITION_WORLD;
focal_plane_normal.y *= vertical_bias;
float dist_to_plane = PlanePointDist(focal_plane_normal, focal_point, world_position);
float blur_amount = clamp((dist_to_plane-DoF)/blur_rate, 0.0, blur_cap);
vec4 color = textureLod(screen_texture, SCREEN_UV, blur_amount);
ALBEDO = color.xyz;
}
Hey, your shader looks really nice, but I can’t get it to work.
It’s showing up in the Editor, but not in game. And also it looks wrong:
I tried setting the focal point to my globalPosition of my character too
I’ve added a demo scene that shows how I set up the shader myself in case its a setup issue. Looking at your screenshot, my best guess for whats wrong is that your DoF (Depth of Field) is too wide at 15 since that is 15 meters of space from your focal point to the edges of the focal plane which everything will remain in focus, and your dimensions may be smaller. As for the blurriness at the edges, your blur cap may simply be too large and allowing more blur than necessary. You can also modify the vertical bias to try to fine tune where the blurring starts as by default the focal plane is very dependent on camera angle.