Skip to main content
added 1281 characters in body; edited tags
Source Link
user171812
user171812
v2f vert(appdata_t IN) {
v2f OUT;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float sX = _ScaleX;
float sY = _ScaleY;
float scaleX = sX * OUT.texcoord.y + 1.0;

float4x4 transformMatrix = float4x4 (
    scaleX,0,0,0,
    0,sY,0,0,
    0,0,1,0,
    0,0,0,1
);

float4 skewedVertex = mul(transformMatrix, IN.vertex);
OUT.vertex = UnityObjectToClipPos(skewedVertex);

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
}
v2f vert(appdata_t IN) {
v2f OUT;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float sX = _ScaleX;
float sY = _ScaleY;
float scaleX = sX * OUT.texcoord.y + 1.0;

float4x4 transformMatrix = float4x4 (
    scaleX,0,0,0,
    0,sY,0,0,
    0,0,1,0,
    0,0,0,1
);

float4 skewedVertex = mul(transformMatrix, IN.vertex);
OUT.vertex = UnityObjectToClipPos(skewedVertex);

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
 

How could one go about solving thisThanks to makea reply from DMGregory the shape proper?problem likely arises from applying a non-affine transformation. In order to remedy this, one could use projective coordinates. What I am quite newreasonably certain I've done is add an extra dimension to working with shaders so the problem mightinput texcoord. This doesn't change anything when I scale everything with a set constant (like 2.0 in this case, picked very arbitrarily) as one would expect, since we would just be entirely on my end theremultiplying and dividing by the same value, but how does one go from this to proper projected coordinates described in the answer to another question, also by DMGregory.

v2f vert(appdata_t IN) {
    v2f OUT;
    OUT.texcoord = float3(IN.texcoord.xy * 2.0, 2.0);
    OUT.color = IN.color;
    float sX = _ScaleX;
    float sY = _ScaleY;
    float scaleX = sX * OUT.texcoord.y/2.0 + 1.0;

    float4x4 transformMatrix = float4x4 (
        scaleX,0,0,0,
        0,sY,0,0,
        0,0,1,0,
        0,0,0,1
    );
    
    float4 skewedVertex = mul(transformMatrix, IN.vertex);
    OUT.vertex = UnityObjectToClipPos(skewedVertex);
    
    #ifdef PIXELSNAP_ON
    OUT.vertex = UnityPixelSnap (OUT.vertex);
    #endif

    return OUT;
}

fixed4 frag(v2f IN) : SV_Target {
    float2 uv = IN.texcoord.xy / IN.texcoord.z;
    fixed4 c = tex2D(_MainTex, uv) * IN.color;
    c.rgb *= c.a;
    return c;
}
v2f vert(appdata_t IN) {
v2f OUT;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float sX = _ScaleX;
float sY = _ScaleY;
float scaleX = sX * OUT.texcoord.y + 1.0;

float4x4 transformMatrix = float4x4 (
    scaleX,0,0,0,
    0,sY,0,0,
    0,0,1,0,
    0,0,0,1
);

float4 skewedVertex = mul(transformMatrix, IN.vertex);
OUT.vertex = UnityObjectToClipPos(skewedVertex);

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
}

How could one go about solving this to make the shape proper? I am quite new to working with shaders so the problem might just be entirely on my end there.

v2f vert(appdata_t IN) {
v2f OUT;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float sX = _ScaleX;
float sY = _ScaleY;
float scaleX = sX * OUT.texcoord.y + 1.0;

float4x4 transformMatrix = float4x4 (
    scaleX,0,0,0,
    0,sY,0,0,
    0,0,1,0,
    0,0,0,1
);

float4 skewedVertex = mul(transformMatrix, IN.vertex);
OUT.vertex = UnityObjectToClipPos(skewedVertex);

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
 

Thanks to a reply from DMGregory the problem likely arises from applying a non-affine transformation. In order to remedy this, one could use projective coordinates. What I am reasonably certain I've done is add an extra dimension to the input texcoord. This doesn't change anything when I scale everything with a set constant (like 2.0 in this case, picked very arbitrarily) as one would expect, since we would just be multiplying and dividing by the same value, but how does one go from this to proper projected coordinates described in the answer to another question, also by DMGregory.

v2f vert(appdata_t IN) {
    v2f OUT;
    OUT.texcoord = float3(IN.texcoord.xy * 2.0, 2.0);
    OUT.color = IN.color;
    float sX = _ScaleX;
    float sY = _ScaleY;
    float scaleX = sX * OUT.texcoord.y/2.0 + 1.0;

    float4x4 transformMatrix = float4x4 (
        scaleX,0,0,0,
        0,sY,0,0,
        0,0,1,0,
        0,0,0,1
    );
    
    float4 skewedVertex = mul(transformMatrix, IN.vertex);
    OUT.vertex = UnityObjectToClipPos(skewedVertex);
    
    #ifdef PIXELSNAP_ON
    OUT.vertex = UnityPixelSnap (OUT.vertex);
    #endif

    return OUT;
}

fixed4 frag(v2f IN) : SV_Target {
    float2 uv = IN.texcoord.xy / IN.texcoord.z;
    fixed4 c = tex2D(_MainTex, uv) * IN.color;
    c.rgb *= c.a;
    return c;
}
Source Link
user171812
user171812

Solving distortion with non-linear scaling in a shader

I am currently working on implementing an older paper in Unity to show the progression of some graphics technologies, and part of that involves sprites being able to cast shadows. A trivial implementation would be to simply use a sprite of the object we already use, change it's colour, and project it underneath whatever casts that shadow.

Example picture of a character with a shadow, moved to display the shadow

Because shadows don't spread out directly the shadow casting object if one were to use a spherical light source, it would be nice to be able to adjust the width of the shadow so that the "top" of the shadow can be wider than the "base" (similar to a trapezium).

My approach has been to use a shader that can modify the vertices with a transformation matrix, as seen in the relevant code snippet below.

v2f vert(appdata_t IN) {
v2f OUT;
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
float sX = _ScaleX;
float sY = _ScaleY;
float scaleX = sX * OUT.texcoord.y + 1.0;

float4x4 transformMatrix = float4x4 (
    scaleX,0,0,0,
    0,sY,0,0,
    0,0,1,0,
    0,0,0,1
);

float4 skewedVertex = mul(transformMatrix, IN.vertex);
OUT.vertex = UnityObjectToClipPos(skewedVertex);

#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
}

Strange effects of the transformation

This unfortunately produces these strange results, which I can't seem to figure out the cause of, but my suspicions are that the UV-coordinates having an origin in one corner of the sprite might have at least something to do with it. Changing the pivot of the sprite from bottom to bottom left doesn't solve it, and instead produces different distortions. The shape displayed in the preview panel of the inspector looks right as well, so I am quite confused.

Preview of a trapezium in the preview panel of the inspector

How could one go about solving this to make the shape proper? I am quite new to working with shaders so the problem might just be entirely on my end there.