Unity Shader Graph:为UI组件编写自定义shader graph

  1. 使用voronoi做动态背景
  2. Unity shader graph:为UI组件编写自定义shader graph
  3. 点击UI按钮,触发水波涟漪效果(使用脚本操作UI)
  4. 水面波光效果

1. 使用voronoi做动态背景

如何把彩色渐变映射给灰度图?
答:直接把灰度图连给彩色渐变的UV输入即可

为什么像素图可以充当彩色渐变?
答:像素图经过图像插值(image interpolation),在Unity里自动呈现渐变效果。

没有Photoshop的话,强烈推荐一个在线绘制像素图的网站:https://www.pixilart.com

2. Unity shader graph:为UI组件编写自定义shader graph

以Image 为例:Unity - Manual: Image (unity3d.com)

Image 组件下有2个属性:Source Image(即sprite)和Color。
这样做的好处是我们可以直接修改这两个参数,而不需要给每个Image都创建一个材质!

我们也可以使用自定义的材质球:

  • Source Image(即sprite)对应材质球shader中的“_MainTex
  • Color对应Vertex Color,——sprite使用mesh的vertex color作为颜色

如果shader里贴图的reference为“_MainTex”,那么最终呈现的是Image 组件下的Source Image,它会覆盖Material下的Texture输入;

如果你不想使用Image 组件下的Source Image,你就是想让Material下的Texture输入生效,那么保持Source Image为空,并且shader里贴图的reference别叫“_MainTex”,叫其他啥名都OK。

3. 点击UI按钮触发水波涟漪效果(使用脚本操作UI)

Shader Graph主要参考这篇教程制作涟漪效果:

傲娇的露易丝:Unity2018 Shader Graph 学习笔记(八) 水波涟漪的实现45 赞同 · 18 评论文章正在上传…重新上传取消​

在Update()里控制Amplitude逐渐归零,就可以模拟涟漪逐渐消失的效果:

using UnityEngine;
using UnityEngine.UI;

public Material ripple_mat;
float temp;

void Start()
    {
        ripple_mat = this.GetComponent<Image>().material;
    }
void Update()
    {
        if (temp < 0.02f)
        {
            ripple_mat.SetFloat("_Amplitude", 0);
        }
        else
        {
            ripple_mat.SetFloat("_Amplitude", Mathf.Lerp(temp, 0, 3.8f*Time.deltaTime));
            temp = ripple_mat.GetFloat("_Amplitude");   
        }
    }

接下来要解决的问题是:鼠标点击UI按钮任一位置,并以此为中心触发涟漪

在shader graph里我添加了2个参数:
UIsize获取UI图片的尺寸(为了让涟漪是个正圆),RippleCenter决定涟漪的中心位置

假设UI图片的尺寸是312x100,那么RippleCenter.x的取值范围就是[0,312],RippleCenter.y的取值范围就是[0,100]

大致思路:
1. 监听按钮点击,获取鼠标在屏幕空间的坐标,即屏幕坐标,Input.mousePosition
2. 使用RectTransformUtility.ScreenPointToLocalPointInRectangle函数,把屏幕坐标转换为UI坐标。关于这个函数的解释:

絮酱酱:【Unity API 翻译】UGUI 屏幕坐标转UI坐标方法 – ScreenPointToLocalPointInRectangle()23 赞同 · 11 评论文章正在上传…重新上传取消​

UI图片以正中心为原点,所以UI坐标的取值范围是:
[-width/2,+width/2],[-height/2,+height/2],并且与scale无关!

3. 显然UI坐标和我们需要的RippleCenter不在一个区间,需要转换一下。
完整的脚本:

using UnityEngine;
using UnityEngine.UI;

public class RippleOnClickUI : MonoBehaviour
{
    public bool enable_Ripple = false;
    public Material ripple_mat;
    public GameObject obj_UI;
    public float amp = 0.2f; //涟漪从这个振幅值开始衰减
    private float temp;//临时记录涟漪振幅的变量
    private Vector2 center;//shader graph里的变量"RippleCenter"
    private Vector2 uiSize;//UI的尺寸,同时也是shader graph里的变量"UIsize"

    void Start()
    {
        ripple_mat = this.GetComponent<Image>().material;
        
        obj_UI=this.transform.gameObject;//获取当前transform组件所在的gameObject
        obj_UI.GetComponent<Button>().onClick.AddListener(Click);
        
        uiSize = obj_UI.GetComponent<RectTransform>().sizeDelta;
        ripple_mat.SetVector("_UIsize", uiSize);
    }

    void Update()
    {
        if (temp < 0.02f)
        {
            ripple_mat.SetFloat("_Amplitude", 0);
        }
        else
        {
            ripple_mat.SetFloat("_Amplitude", Mathf.Lerp(temp, 0, 3.8f*Time.deltaTime));
            temp = ripple_mat.GetFloat("_Amplitude");   
        }
    }

    public void Click()
    {
        if (enable_Ripple)
        {
            ripple_mat.SetFloat("_Amplitude", amp);
            temp = ripple_mat.GetFloat("_Amplitude");

            RectTransformUtility.ScreenPointToLocalPointInRectangle(
            obj_UI.GetComponent<RectTransform>(),//The RectTransform to find a point inside.
            Input.mousePosition,//Screen space position.
            Camera.main,//The camera associated with the screen space position.
            out Vector2 localPoint);//Point in local space of the rect transform.

            center.x = localPoint.x + uiSize.x / 2;
            center.y = localPoint.y + uiSize.y / 2;

            ripple_mat.SetVector("_Center", center);
        }
    }
}

4. 水面波光效果

教程:【シェーダーグラフメモ その50】Voronoiを利用した水面エフェクト - rn.log (hatenablog.com)

----------------------------------------------------------

上面截图里的文字都是图片,换成text就惨了,啊我没有想到过text不是image!而是等价于佷多张image,一个字符就是一张图片,并且他们来自同一张图集(atlas)!

  • text由一个个字符组成(character),如果不给Alpha或者shader里没有"_MainTex"的话,出来的就是一个个矩形方块,相当于一张张小图片
  • 我猜啊,text组件根据字体和文本,背着我们生成了一张Font Texture(图集,atlas),上面排列着文本包含的字符形象(乱序),然后每个字符方块在这张临时的Font Texture上有自己对应的坐标,对应自己的字符形象
  • 所以,给text做水波涟漪效果,相当于是在好几张小图片上做效果,这肯定不对啊……唉,我搞不定了……可能需要把text写成texture再当成image来处理吧……

同理,如果你的sprite来自于sprite atlas(图集),它将和text一样不能适用这个shader graph。切分sprite只是方便操作,实际渲染的时候其实只有一张图集。shader graph只获取贴图和UV数据,而无从得知单个被切分的sprite的信息。
参考:

https://forum.unity.com/threads/shader-graph-being-shared-by-all-the-images-of-multiple-sprite.734318/​forum.unity.com/threads/shader-graph-being-shared-by-all-the-images-of-multiple-sprite.734318/

https://forum.unity.com/threads/shader-graph-and-multiple-sprite-mode.706733/​forum.unity.com/threads/shader-graph-and-multiple-sprite-mode.70673

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Shader Graph中实现HDRP(High Definition Render Pipeline)的UI材质,首先需要了解HDRP的特点和要求。HDRP是Unity的高清渲染管线,用于呈现高质量的图形效果。在UI材质中,我们希望能够使用HDRP的功能和效果来提升UI元素的可视效果。 首先,我们需要创建一个新的HDRP UI着色器。在Shader Graph中,可以使用"Create"按钮创建一个新的着色器图。然后,在着色器图中,我们可以使用各种节点来实现所需的效果。 在这个HDRP UI着色器中,我们可以添加各种节点来实现不同的效果。例如,使用"Texture 2D"节点来加载UI材质的纹理贴图,使用"Sampler State"节点来设置材质的采样状态,以及使用"Color"节点来调整UI元素的颜色。 除了基本的节点,我们还可以使用HDRP专用的节点来实现更高级的效果。例如,使用"Decal Node"节点来添加镜面反射效果,使用"Sub Graph"节点来嵌入自定义的子图形,以实现自定义的效果。 在配置完成所有节点之后,我们可以使用"Master Node"节点来输出最终的UI材质。通过连接各个节点,在不同的输入和输出之间传递数据和参数,从而实现预期的HDRP效果。 最后,我们可以在Unity中应用我们创建的HDRP UI材质。与常规的UI材质不同,我们需要将其应用于使用HDRP渲染管线的相机和UI元素上。在Unity的Inspector窗口中,选择使用HDRP渲染管线的相机,并将我们创建的HDRP UI材质分配给UI元素的材质插槽。 通过这样的步骤,我们可以在Shader Graph中实现HDRP UI材质。这样,我们可以利用HDRP提供的高级渲染功能和效果来提升UI元素的质量和视觉效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值