世界空间中Unity Shader Graph的2D纹理位移

3
我正在制作一款2D俯视角度的游戏。我有一个物体,它在单个大纹理上移动,并在其上投下阴影(只是模糊的暗色精灵)。然而,我发现由于我的纹理有凸起、岩石、褶皱等,它看起来像阴影精灵只是悬浮在地面上方。 因此,我想到可以使用我的纹理作为位移贴图,根据纹理表面扭曲阴影精灵。我正在尝试在Shader Graph中实现它,但我无法获得底层纹理的正确位置和比例以将阴影投射到上面。
我尝试实现了一个简化版本的着色器,精确复制它悬浮在地面纹理部分的内容。

enter image description here

在这种情况下,缩放似乎有问题,结果的纹理比原始纹理要小得多。我不确定位置是否正确,但似乎也有问题。我错过了什么吗?还是有更简单的方法实现它?
先行致谢。
1个回答

2
我不确定这是否是最优雅的解决方案,但我找到了一个。
我应该使用平铺和偏移节点来缩放和移动地面纹理的UV。这是着色器图:

enter image description here

现在这个着色器使得物体将其所放置的地面纹理部分投影到自身上。它似乎与纹理完美对齐。
地面位置是通过代码计算的:
[RequireComponent(typeof(SpriteRenderer))]
public class displaced_shadow : MonoBehaviour
{
    SpriteRenderer sr;
    Rect rect;
    MaterialPropertyBlock material_properties;
    float pixels_per_unit;

    public Vector2 Size //get size of the texture in Unity units
    {
        get { return new Vector2(rect.width * transform.localScale.x/ pixels_per_unit, rect.height * transform.localScale.y/ pixels_per_unit); } 
    }

    private void Awake()
    {
        sr = GetComponent<SpriteRenderer>();
        rect = sr.sprite.rect;
        pixels_per_unit = sr.sprite.pixelsPerUnit;
        material_properties = new MaterialPropertyBlock();
    }

    // Update is called once per frame
    void Update()
    {
        Vector2 relative_position = CalculateRelativePostion();
        FeedMaterial(relative_position);
    }

    private Vector2 CalculateRelativePostion() //calculate the position relative to the background in [0,1] range
    {
        if (background_floor.This == null) return Vector3.zero;

        Vector2 bg_position = background_floor.This.Position; //get the size and position of the background texture
        Vector2 bg_size = background_floor.This.Size;

        float origin_x1 = transform.position.x - Size.x/2f; //calculate the top left corner positions in case textures have their origins in the center
        float origin_y1 = transform.position.y - Size.y / 2f;
        float origin_x2 = bg_position.x - bg_size.x / 2f;
        float origin_y2 = bg_position.y - bg_size.y / 2f;

        float x = (origin_x1 - origin_x2) / bg_size.x; //get the [0,1] position of the object relative to the ground texture
        float y = (origin_y1 - origin_y2) / bg_size.y;

        return new Vector2(x, y);
    }

    private void FeedMaterial(Vector2 relative_position)
    {
        sr.GetPropertyBlock(material_properties);
        material_properties.SetVector("_GroundPosition", relative_position);
        sr.SetPropertyBlock(material_properties);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接