【shaderforge学习笔记】 Rotator节点

时间:2022-04-20 04:01:35

ShaderForge Rotator节点

一、节点介绍

旋转器
【shaderforge学习笔记】 Rotator节点

输出的是输入的uv以[piv]为锚点旋转后[ang] (单位为弧度)的uv信息。如果ang没有连线,或者ang连线到time节点上,那么[spd]会控制旋转速度。

二、Rotator节点的输入

1. Piv

Piv是旋转操作的锚点,是一个二维数据(x,y)
uv坐标是从(0,0)->(1,1)的二维坐标系,左下角坐标(0,0),右上角坐标(1,1),中心点坐标(0.5,0.5)
举例:以左下角(0,0)为锚点旋转
【shaderforge学习笔记】 Rotator节点

2. Ang

旋转的角度(以弧度为单位,2PI为一周)
【shaderforge学习笔记】 Rotator节点

将弧度换算成角度

角度值 *PI/180 = 弧度值

【shaderforge学习笔记】 Rotator节点

3. Spd

旋转的速度,默认值为1.0。
- 当Ang是一个常量的时候,Spd作为Ang的倍数,Spd*Ang是作为实际旋转的角度。
- 当Ang是时间变量的时候,Spd控制着旋转的速度。
【shaderforge学习笔记】 Rotator节点

三、Rotator节点的输出

旋转后的uv坐标


四、小实例 漩涡扭曲效果

如果ang是单个数据,那么uv会整体旋转;
如果ang输入的是一个一维数组,那么我们就可以通过数组来控制对应部位的旋转扭曲的强度。

【shaderforge学习笔记】 Rotator节点
扭出一朵小花花送给你!~

五、自实现Untiy Shader代码实现Rotator节点的功能

我们来循序渐进的使用书写unity shader代码模拟旋转器节点的功能

1. 围着图片中心匀速旋转

写法

Shader "Hidden/testRotator"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
        }
        Pass
        {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }

            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;

            fixed4 frag (v2f i) : SV_Target
            {

                float ang = _Time.y;
                float spd = 1.0;
                float2 piv = float2(0.5,0.5);

                // 计算旋转矩阵
                float rotateCos = cos(spd*ang);
                float rotateSin = sin(spd*ang);
                float2x2 rotateM = float2x2(rotateCos,-rotateSin,rotateSin,rotateCos);
                // 移动纹理位置,将旋转中心到(0,0)乘以旋转矩阵,再移回原来的位置
                float2 uvNew = mul(i.uv-piv,rotateM)+piv;

                fixed4 col = tex2D(_MainTex, uvNew);
                float3 finalColor = col.rgb;
                fixed4 finalRGBA = fixed4(finalColor,1);
                return finalRGBA;
            }
            ENDCG
        }
    }
}

原理

我们根据ang和spd确定旋转角度,有了旋转角度和旋转中心我们就可以计算出旋转矩阵,将原来的uv乘以旋转矩阵就得到了新的uv

绕任意点的二维旋转

绕原点的旋转是二维旋转最基本的情况,当我们需要进行绕任意点旋转时,我们可以把这种情况转换到绕原点的旋转,思路如下:
1. 首先将旋转点移动到原点处
2. 绕原点的旋转
绕原点旋转θ的矩阵如下所示:
【shaderforge学习笔记】 Rotator节点
3. 再将旋转点移回到原来的位置
参考:旋转变换(一)旋转矩阵

效果展示

【shaderforge学习笔记】 Rotator节点

2. 可调节旋转的锚点位置,旋转角度

以锚点位置为中心,旋转ang*spd大小

写法

Shader "Hidden/testRotator"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Ang ("Ang", Range(0.0, 6.28)) = 0.0
        _PivX("Pivot X",Float) = 0.5
        _PivY("Pivot Y",Float) = 0.5
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
        }
        Pass
        {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }

            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 _Ang;
            float _PivX;
            float _PivY;
            // float _spd;
            fixed4 frag (v2f i) : SV_Target
            {

                float ang = _Ang;
                // float ang = _ang;
                float spd = 1.0;
                // float spd = _spd;
                float2 piv = float2(_PivX,_PivY);

                // 计算旋转矩阵
                float rotateCos = cos(spd*ang);
                float rotateSin = sin(spd*ang);
                float2x2 rotateM = float2x2(rotateCos,-rotateSin,rotateSin,rotateCos);
                // 移动纹理位置,将旋转中心到(0,0)乘以旋转矩阵,再移回原来的位置
                float2 uvNew = mul(i.uv-piv,rotateM)+piv;

                fixed4 col = tex2D(_MainTex, uvNew);
                float3 finalColor = col.rgb;
                fixed4 finalRGBA = fixed4(finalColor,1);
                return finalRGBA;
            }
            ENDCG
        }
    }
}

设置Ang,Piv属性,在Inspector面板中控制属性值

效果展示

【shaderforge学习笔记】 Rotator节点

3. 可调节旋转的锚点位置,旋转速度

写法:

Shader "Hidden/testRotator"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        // _Ang ("Ang", Range(0.0, 6.28)) = 0.0
        _PivX("Pivot X",Float) = 0.5
        _PivY("Pivot Y",Float) = 0.5
        _Spd("Spd", Range(0.0,10.0)) = 1.0
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
        }
        Pass
        {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }

            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 _Ang;
            float _PivX;
            float _PivY;
            float _Spd;
            fixed4 frag (v2f i) : SV_Target
            {

                float ang = _Time.y;
                float spd = _Spd;
                float2 piv = float2(_PivX,_PivY);

                // 计算旋转矩阵
                float rotateCos = cos(spd*ang);
                float rotateSin = sin(spd*ang);
                float2x2 rotateM = float2x2(rotateCos,-rotateSin,rotateSin,rotateCos);
                // 移动纹理位置,将旋转中心到(0,0)乘以旋转矩阵,再移回原来的位置
                float2 uvNew = mul(i.uv-piv,rotateM)+piv;

                fixed4 col = tex2D(_MainTex, uvNew);
                float3 finalColor = col.rgb;
                fixed4 finalRGBA = fixed4(finalColor,1);
                return finalRGBA;
            }
            ENDCG
        }
    }
}

效果展示

【shaderforge学习笔记】 Rotator节点

4.自实现漩涡扭曲效果

写法

Shader "Hidden/testRotator"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _AngTex ("Ang Texture", 2D) = "white" {}
        _PivX("Pivot X",Float) = 0.5
        _PivY("Pivot Y",Float) = 0.5
        _Spd("Spd", Range(0.0,10.0)) = 1.0
    }
    SubShader
    {
        Tags {
            "RenderType"="Opaque"
        }
        Pass
        {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }

            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;
            sampler2D _AngTex;
            float _PivX;
            float _PivY;
            float _Spd;

            fixed4 frag (v2f i) : SV_Target
            {
                float4 colAng = tex2D(_AngTex, i.uv);
                float ang = colAng.r;
                float spd = _Spd;
                float2 piv = float2(_PivX,_PivY);

                // 计算旋转矩阵
                float rotateCos = cos(spd*ang);
                float rotateSin = sin(spd*ang);
                float2x2 rotateM = float2x2(rotateCos,-rotateSin,rotateSin,rotateCos);
                // 移动纹理位置,将旋转中心到(0,0)乘以旋转矩阵,再移回原来的位置
                float2 uvNew = mul(i.uv-piv,rotateM)+piv;

                fixed4 col = tex2D(_MainTex, uvNew);
                float3 finalColor = col.rgb;
                fixed4 finalRGBA = fixed4(finalColor,1);
                return finalRGBA;
            }
            ENDCG
        }
    }
}

效果展示

【shaderforge学习笔记】 Rotator节点
同样一朵小花出现啦!~

参考:

Unity3D开发之Shader实现扭曲效果