Unity Shader Graph中的Worldspace 2d纹理置换

Posted

技术标签:

【中文标题】Unity Shader Graph中的Worldspace 2d纹理置换【英文标题】:Worldspace 2d texture displacemet in Unity Shader Graph 【发布时间】:2020-06-29 16:31:00 【问题描述】:

我正在开发一款 2D 自上而下的游戏。我有一个在单个大纹理上移动并在其上投射阴影的对象(只是一个模糊的深色精灵)。然而我发现,由于我的纹理有凹凸、岩石、折痕等,看起来影子精灵只是在地面上方盘旋。 所以我想我可以使用我的纹理作为置换贴图来根据纹理的表面扭曲阴影精灵。我正在尝试在 Shader Graph 中实现它,但我无法获得底层纹理的正确位置和比例来投射阴影。 我尝试实现一个简化版本的着色器,它精确地再现了它悬停在上方的Ground Texture 部分。

在这种情况下,缩放似乎已关闭,生成的纹理比原始纹理小很多。我不确定这个位置,但它似乎也关闭了。我错过了什么吗?还是有更简单的方法来实现这一点?

提前致谢。

【问题讨论】:

【参考方案1】:

我不确定这是否是最优雅的解决方案,但我找到了。

我应该使用Tiling and Offset 节点来缩放和移动地面纹理的UV。这是着色器图:

现在,这个着色器使对象将其放置在其上的地面纹理部分投影到自身上。它似乎与纹理完美对齐。

地面位置在代码中计算:

[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);
    

【讨论】:

以上是关于Unity Shader Graph中的Worldspace 2d纹理置换的主要内容,如果未能解决你的问题,请参考以下文章

Unity,如何在Shader Graph中设置shader标签“DisableBatching”=“True”?

Unity Shader Graph尝试

unity shader可视化工具——Shader Graph

Unity关闭shader中的光照模型以及如何自定义光照模型

Unity使用Shader Graph实现遮挡剔除

Unity使用Shader Graph实现遮挡剔除