欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)

程序员文章站 2022-06-23 22:22:37
...

原理

在网上搜了一下贴图沿中心缩放的代码,发现并没有,自己研究了一下午,最后得出了结论
对原理不感兴趣的同学可以直接跳到第二部分的shader实现上,下面讲原理部分
首先,在Unity中创建一个Cube,一个Standard模式的Material,然后导入我下面这张用PS制作的测试图(中心稍微有一丢丢对不齐,不过用于测试足够了)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
把图片赋给新建材质的Albedo上,然后把材质赋给新建的Cube,如下图所示
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
接下来进行几组UV的缩放和平移的测试
默认情况下,Tiling值都是(1,1),而Offset是(0,0),如下图所示
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
先试试将Tiling值调为大于1的情况
将Tiling逐渐调为2(Tiling为(2,2)时,如下图所示),可以看到图片在沿着左下角进行缩小,最后图片变成2x2的形式
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
但这不是我们要的效果,接着进行Offset的调整,使左下角的图案移动到正中心
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
移动完成后,会发现Offset的数值为(-0.5,-0.5)
得出第一组数据
Tiling(2,2)
Offset(-0.5,-0.5)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
接着试试Tiling为(3,3),出现如下图片
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
看起来似乎是我们要的效果,但还是要把左下角的图像向中心移动
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
移动完之后可以得出数据
Tiling(3,3)
Offset(-1,-1)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
Tiling为(4,4)
Offset(-1.5,-1.5)
如下图
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
试试非整数缩小的数据(比如1.5)
Tiling为(1.5,1.5)
Offset(-0.25,-0.25)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
看到这里,应该有点感觉了
试试小于1的情况
Tiling为(0.5,0.5)
Offset(0.25,0.25)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
Tiling为(0.8,0.8)
Offset(0.1,0.1)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
看到这里,基本上应该可以推断出UV沿中心缩放的原理了,不过还是说明一下
Tiling为(2,2)时
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
Tiling为(4,4)时
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
以此类推,小于1的情况类似
Tiling为(0.8,0.8)时
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
由此我们推出UV沿中心缩放的公式
缩放量=(缩放量-1)/-2
接下来,谈谈unity中如何用shader实现这个效果

Unity中Shader的实现

大家可以按照我的步骤创建一个简单的shader,然后将这个shader进行几句简单的代码改写
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
shaer部分的代码

Shader "Hidden/NewImageEffectShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}                                          //贴图
		_Progress("Progress", Range(0,10)) = 1                                         //缩放量,负责联系外界滑动数值与内部shader的数值
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;
			float _Progress;                                                         //声明缩放量,负责参与shader中运算
			float4 _MainTex_ST;                                                      //声明一个四维数,负责进行UV缩放平移的计算

            fixed4 frag (v2f i) : SV_Target
            {
				_MainTex_ST.xy = _Progress;                                          //将缩放量赋给UV Tiling
				_MainTex_ST.zw = (_Progress - 1)*-0.5;                               //根据缩放量计算UV Offset
                fixed4 col = tex2D(_MainTex, i.uv*_MainTex_ST.xy+_MainTex_ST.zw);    //最后将计算完的UV值附上
                return col;
            }
            ENDCG
        }
    }
}

这个时候,滑动这个滑动条,就可以看到我们的贴图沿着中心进行缩放了(觉得缩放量和数值是反过来的同学可以在运算的时候将缩放量取倒数就可以了)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)

UE4中的3种实现方法

方法1(使用虚幻自带的节点)

在虚幻中创建一个材质,同样也是将文章中的第一张图片赋给材质,然后将这个材质赋给Cube
节点如下
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
通过这个材质创建一个材质实例
然后打开材质实例,启用这个数值就可以进行贴图沿中心缩放了
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)

方法2(使用蓝图节点自己计算)

节点如下
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
同样也是创建一个材质实例,调节scale值就可以进行沿中心缩放

方法3(使用custom节点进行运算)

虚幻4编辑器里能用的Shader语言是HLSL,而且只能通过custom节点才能进行编写
第一种写法(这里贴图用的是texture sample)
附上custom里的代码

	float4 a=ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material.Texture2D_0, Material.Texture2D_0Sampler, UV*Scale-(Scale-1)/2, false));
	return a;

custom里的节点设置
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
第二种写法(这里贴图用的是texture object)
附上custom里的代码

float3 col = Texture2DSample(Tex, TexSampler, UV*Scale-(Scale-1)/2);
return col;

custom里的节点设置
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
使用UnityShader实现图片沿中心缩放的功能(附UE4中的3种实现方法)
这里推荐第二种写法(贴图为Texture Object),同样将材质生成一个材质实例,改变材质实例中的Scale值,就可以实现贴图沿着中心进行缩放的效果