#How to create a nine patch slice shader

2 messages · Page 1 of 1 (latest)

slim patrol
#

I found the following shader code on this site: https://godotshaders.com/shader/9-slice-shader/ and want to adapt it to support tile and tile_fit modes, just like a nine patch rect. So I added some placeholders to the process_axis function:

shader_type canvas_item;

const int STRETCH = 1;
const int TILE = 2;
const int TILE_FIT = 3;

uniform vec2 scale;

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

uniform int mode : hint_range(1, 3);


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) {
        if (mode == STRETCH) {
            return map(coord, start * pixel, 1.0 - end * pixel, start * texture_pixel, 1.0 - end * texture_pixel);
        }
        else if (mode == TILE) {
            // CODE GOES HERE
        }
        else if (mode == TILE_FIT) {
            // CODE GOES HERE
        }
        else {
            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);
}

At least I feel that's were the changes should happen, but my attempts at tiling aren't quite there yet, could someone help me out?

slim patrol
#

inserting

            float ratio = texture_pixel / pixel;
            coord *= ratio;
            coord = fract(coord);
            return coord;
        }```
seems to tile the texture, but I'm not sure how to handle margins with it.