I have a 9-slice shader working mostly nicely:
Here, both the sprites are separate images, so the shader code works well:
varying vec4 color;
varying vec2 texCoord;
uniform sampler2D tex;
uniform vec2 u_dimensions;
uniform vec2 u_border;
float map(float value, float originalMin, float originalMax, float newMin, float newMax) {
return (value - originalMin) / (originalMax - originalMin) * (newMax - newMin) + newMin;
}
// Helper function, because WET code is bad code
// Takes in the coordinate on the current axis and the borders
float processAxis(float coord, float textureBorder, float windowBorder) {
if (coord < windowBorder)
return map(coord, 0, windowBorder, 0, textureBorder) ;
if (coord < 1 - windowBorder)
return map(coord, windowBorder, 1 - windowBorder, textureBorder, 1 - textureBorder);
return map(coord, 1 - windowBorder, 1, 1 - textureBorder, 1);
}
void main(void) {
vec2 newUV = vec2(
processAxis(texCoord.x, u_border.x, u_dimensions.x),
processAxis(texCoord.y, u_border.y, u_dimensions.y)
);
// Output the color
gl_FragColor = texture2D(tex, newUV);
}
External from the shader, I upload vec2(slice/box.w, slice/box.h) into the u_dimensions variable, and vec2(slice/clip.w, slice/clip.h) into u_border. In this scenario, box represents the box dimensions, and clip represents dimensions of the 24x24 image to be 9-sliced, and slice is 8 (the size of each slice in pixels).
This is great and all, but it's very disagreeable if I decide I'm going to organize the various 9-slice images into a single image sprite sheet.
Because OpenGL works between 0.0 and 1.0 instead of true pixel coordinates, and processes the full images rather than just the contents of the clipping rectangles, I'm kind of stumped about how to tell the shader to do what I need it to do. Anyone have pro advice on how to get it to be more sprite-sheet-friendly? Thank you!