9-slice shader

Simple shader that implements 9-patch/9-slice behaviour.

There are situations when you can’t use 9-patch rect but have to use Sprite. This shader is exactly for theese situations.

Considerations:

Don’t overuse it. When you use shader in Sprite it will require separate draw call interfearing with batching. thus if have too many(more than few dozen I guess) of such sprites your performance can degrade.

For this to work you need to add this code to your Sprite:
tool
extends Sprite

func _ready():
    set_notify_transform(true)

func _notification(what):
    if what == NOTIFICATION_TRANSFORM_CHANGED:
        get_material().set_shader_param("scale", scale)

Shader code
shader_type canvas_item;

uniform vec2 scale;

uniform int right;
uniform int top;
uniform int left;
uniform int bottom;

float map(float value, float originalMin, float originalMax, float newMin, float newMax) {
    return (value - originalMin) / (originalMax - originalMin) * (newMax - newMin) + newMin;
} 

float process_axis(float coord, float pixel, float texture_pixel, float start, float end) {
	if (coord > 1.0 - end * pixel) {
		return map(coord, 1.0 - end * pixel, 1.0, 1.0 - texture_pixel * end, 1.0);
	} else if (coord > start * pixel) {
		return map(coord, start * pixel, 1.0 - end * pixel, start * texture_pixel, 1.0 - end * texture_pixel);
	} else {
		return map(coord, 0.0, start * pixel, 0.0, start * texture_pixel);
	}
}

void fragment() {
	vec2 pixel_size = TEXTURE_PIXEL_SIZE / scale;
	
	vec2 mappedUV = vec2(
		process_axis(UV.x, pixel_size.x, TEXTURE_PIXEL_SIZE.x, float(left), float(right)),
		process_axis(UV.y, pixel_size.y, TEXTURE_PIXEL_SIZE.y, float(top), float(bottom))
	);
	COLOR = texture(TEXTURE, mappedUV);
}
Tags
9-patch, 9-slice, nine-patch, nine-slice
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

slice texture

Slice and Fade out

Wind Waker 2d Water Shader (GODOT 4)

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
yikescloud
yikescloud
1 year ago

I make a simple benchmark test for the shader, it almost has same performance with the origin sprite, so maybe you don’t need worry about the performance problem:D

boruok
boruok
4 months ago

doesn’t work properly with AtlasTexture