• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Shaders Perspective skew - (without the perspective)

DesArts

Member
I want to scale the top and bottom of a sprite without affecting the vertical axis at all. The sprite height would remain the same and each pixel row stays at the same height. The top and bottom would also need to be able to move left and right independently, basically shear. This is for a pixel art game.

So, very much like draw_sprite_pos but very different in how the final image turns out.
draw_sprite_pos clearly has issues which won't work for this. There are shaders which replace that with full perspective correction, but clearly, I want something different here. Just drawing it with 3D perspective won't work here as it would blow out the top pixels and shrink the bottom of the sprite down to nothing.


If you want to get an idea for the parameters it'd be like draw_sprite_perspective_skew(sprite, img, top_width, bottom_width, height(this one doesn't matter), top_centre_x, bottom_centre_x, top_y)
I think some other shader would be needed with a vertex buffer, however I cannot deal with shaders too well yet. I have no experience writing them.
I'd appreicate any help with this sort of thing.
 
Is the sprite always going to be squished toward its own center on the bottom? Or would it be squished toward the center of the view?

Here's what I mean by toward the center of the view:
1600638176722.png
The white squares being where the sprites would be drawn if they weren't being manipulated at all.
 
Last edited:

DesArts

Member
That pic is basically the use case I am using it for, yeah, just without y distortion.I got all of that down, it's just a vertex buffer for each one, but it of course distorts. Even in your image the head is way taller than it'd really be in the sprite I assume, and the legs are shorter. That's my issue.

So it would be centred towards the room centre (well, a chosen x position) in practice, but in reality I'd like to be able to decide how skewed it is with pixel amounts or something like that.
 
This assumes you are moving vertices along the camera's x axis. Anything else will require a different solution.

Since you are using a vertex buffer, you can just add extra pieces of information to the vertex format.

So try this, add a "depth" value, if you don't have one already.

What you can do in the vertex shader is alter the gl_Position like this:

gl_Position.w = depth;
gl_Position.yz *= depth;

The first line adds a kind of perspective to the projection. How? Behind the scenes, the x and y and z elements of gl_Position are automatically divided by w. So a depth of 1, would result in no change of the vertex position. (Orthographic projections will result in a w value of 1) A depth of 2 would move the vertex half way to the view's center, along each axis. To cancel out the movement of the vertex along the y and z axes (z axis will affect depth buffer), then just multiply those two components by depth, like is shown in the second line.

This is going to move vertices toward the center of the view along the camera's x axis. If you want to move it toward any other point, you'll have to add some kind of offset to gl_Position.x.
 
Oh, the reason the head looks too tall is because the amount of stretching in relation to tye height of the sprite is totally arbitrary in that picture.

What you could do is make the sprites wider.

Note: If you're going to be moving the camera up and down, it would be better just to use a perspective projection.
 
Last edited:

DesArts

Member
I really appreciate the help though I think my issue is different. While I mentioned requirements for the shader, I actually have the positioning side of things sorted just fine via the actual vertex positions used:

Here's the issue: my equally spaced grid is distorted vertically, not just horizontally. the top grid is way taller than the bottom grid, while I want that made flat. I just want the vertical lines to slant I guess.

This is using an asset:
This asset uses a shader on a buffer to correct it for perspective, realistically.
Because of course the real function gives horrid skewed effect like below:

Same with buffers without a shader. The shader included does fix this but it doesnt do what I need as you can see. I need a shader that can correct a perspective and skewed rectangle drawn like you showed (and like above) but only affect the x axis. I want all the horizontal lines perfectly linear and preserved basically.

It's hard to explain I suppose, but hopefully that makes it clear.
 

DesArts

Member
I guess the best way to picture what I want is if I individually scaled each individual pixel row of a sprite to be the right width, and that's it. Same effect.
Anyone able to help?
 
Suppose you wanted to do one unbroken repeating texture. You could just draw a single quad using the following shader:
1600811883715.png
vertex shader:
Code:
    attribute vec3 in_Position;
    attribute vec2 in_TextureCoord;
    varying vec2 v_vTexcoord;
    void main() {
        gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4( in_Position, 1.0);
        v_vTexcoord = in_TextureCoord;
    }
fragment shader:
Code:
    varying vec2 v_vTexcoord;
    const vec3 S = vec3(4.0,8.0,2.0);
    void main() {
        vec2 uv = v_vTexcoord;
        uv.x = (uv.x - 0.5)/(1.0 - uv.y + uv.y*S.x/S.y);
        gl_FragColor = texture2D( gm_BaseTexture, uv*S.xz );
    }
In this case, the texture must be on it's own texture page.
S.x = number of texture repeats on top along x axis.
S.y = number of texture repeats on bottom along x axis.
s.z = number of texture repeats along y axis.
 

DesArts

Member
Okay I get the approach and honestly thankyou, It's not something I would have considered. It solves the stupid distortion issue by doing it all in-shader. Two issues however:

This is what draws for me, no idea why. I set it to repeat and separate texture page etc, and played with looping values a bit. It's drawn as a flat rectangle from each end of the room, just down to the sprite height from the top, with vertexes at top left, top right, bottom left, bottom right.

The other thing would be allowing for scroll offset value which scales with the horizontal repeat (so higher repeat values would move slower). I can possibly figure this out myself once it's drawing properly, but any guidance would be appreciated.

And again, thanks for the idea in general, it will definitely be the solution.
 
Top