0
\$\begingroup\$

I am trying to achieve a special texture stretching effect in my shader. Here is how I define my uv before sampling my texture, nothing really special.

// uv_ST contains the tiling and offset values
uv.xy = uv.xy * uv_ST.xy + uv_ST.zw

This gives the standard tiling/stretching and offset behaviour when you tile/stretche a clamped texture as you can see in the image below. First is normal, second is offset and last is stretching.

enter image description here

But I want to avoid the deformation behaviour when stretching, I want to keep margins when stretching my texture or simply cut it in the middle and stretching it. Here is an illustration below.

enter image description here

How could I do that inside my shader when defining my uvs before sampling the texture ?

\$\endgroup\$
4
\$\begingroup\$

So, essentially what you're looking for is 9 Slice Scaling. However that's only good for stretching out a texture so the edges and corners remain undeformed (sort of).

  • The corners are 1:1 in both directions.
  • The edges are 1:Y or X:1 depending on if they're horizontal or vertical (that is, non-uniform, but such that the stretched direction is unnoticed because all the pixels are the same).
  • The center is then X:Y and is usually unnoticed because its just a solid fill.

But it seems like you're needing the center to be unstretched too. There is a way to accomplish this, but you'll have to code it yourself using the same sort of math that makes 9-slice scaling work. And you seem to only be stretching in one direction (that'll make it easier).

There's no pre-build solution for your use-case, but it should be easy to work out! Just count how many pixels you need to leave undistorted and make sure that you draw that area at it's exact size. Then you can stretch out the middle to fill the needed space (or at least, stretch out the next chunk) and then draw the other edge at the exact size again.

\$\endgroup\$
-2
\$\begingroup\$

The Nine Patches algorithm is a really nice and powerful solution if you are using textures but I ended up by using a fully procedural solution.

I am just drawing a round box like this.

float udRoundBox( vec3 p, vec3 b, float r )
{
  return length(max(abs(p)-b,0.0))-r;
}

You can simply avoid the 3rd dimension if you don't need it. This method comes from the Distance function article from Inigo Quilez.

\$\endgroup\$
2
  • \$\begingroup\$ "I am just drawing a round box like this." - following code does not seem to do anything with drawing \$\endgroup\$
    – Kromster
    Jun 6 '17 at 10:45
  • \$\begingroup\$ @Kromster it's drawing using signed distance fields, where shapes are formed by computing the distance from each sample point to the closest shape edge. This doesn't answer the question of stretching "textures" but it does allow drawing of malleable, crisp, and vector-like shapes. \$\endgroup\$
    – DMGregory
    Jun 6 '17 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.