Skew a sprite

2018-10-01%2020_06_35-LNPOverlayWindow

I want to skew a sprite like this. Any ideas on how to easily do this?

2 Likes

I have not tinkered with this but I believe there are two options.

  1. Move the vertices in a shader.
  2. Render the sprite using a skew matrix with the projection.
1 Like

I am going to learn about shaders pretty soon. I am not looking forward to it at all.

2 Likes

Here is some progress with using a shader

SkewSprite.zip (2.7 KB)

But if there are multiple sprites with it this happens? Caused by batching?

2 Likes

Trying to break batching with changing the fp doesn’t help, it does increase drawcalls though.

Haven’t looked at your code, but the vertex positions are (currently) in world space when they arrive to the shader. That may cause problems.

Here’s the vp code

uniform mediump mat4 view_proj;

// positions are in world space
attribute mediump vec4 position;
attribute mediump vec2 texcoord0;

varying mediump vec2 var_texcoord0;
uniform lowp vec4 skew;

void main()
{
    mat4 transform = mat4(
        1,skew.x,0,0,
        skew.y,1,0,0,
        0,0,1,0,
        0,0,0,1);        
        gl_Position = view_proj * (vec4(position.xyz, 1.0) * transform);
    var_texcoord0 = texcoord0;
}

Any idea on how to change it?

You apply the skew to the world space positions of the vertices. You need to first get hold of model space coordinates. I think it’s possible to calculate an inverse of the world space transform and apply that first to get back to model space.

We have a couple of issues in the backlog to sort this out.

1 Like

I’m not much of a shader pro yet to know how to do that unfortunately.

It does make sense now that you mention that why this behavior is seen though. If I set the material y skew in the editor to 0.2 I see this in the editor.

0%20-%20SkewSprite

So the process would be to convert back to model space, apply the skew transform, then convert back to world space however that’s done?

Yes, currently that is the only way. There are plans to make it possible to get vertices in model space instead which would make this much easier.

1 Like

Is it possible now or do I need to wait for features to change?

Did a forum search, DEF-2518 “adding inverse world matrix so you can translate positions to object space if needed” if this can be prioritized in the future it would be nice!

Was talking with a friend about this and he said if we could get local UV space for sprites (rather than shared atlas UV space) we could use the UVs for skew shaders easily too. Local UV space is also needed for many effects that would be nice such as placing a gradient over the actual size of a sprite and not the entire atlas space the sprite texture is on.

Even though inverse() isn’t supported it still works in desktop builds… but things break still.

uniform mediump mat4 view_proj;
uniform mediump mat4 world;

// positions are in world space
attribute mediump vec4 position;
attribute mediump vec2 texcoord0;

varying mediump vec2 var_texcoord0;
uniform lowp vec4 skew;
varying highp vec4 var_modelSpacePosition;

void main()
{
    mat4 transform = mat4(
        1,skew.x,0,0,
        skew.y,1,0,0,
        0,0,1,0,
        0,0,0,1);        
    //
    gl_Position = view_proj * world * transform * inverse(world) * vec4(position.xyz, 1.0);
    var_texcoord0 = texcoord0;
}

Appears that batching is the issue with this version currently assuming I was also using a custom inverse function as the model matrix is for the entire batch. I tried to break batching with custom values but had not impact.

Also note I have not been able to reproduce what happened in that previous video in the editor where moving one sprite impacted the others. No idea what is going on there!

At the time I was testing adding / removing the world / inverse(world) from the vp.