Unity3D教程宝典之Shader篇:第二十六讲ImageEffects_Twirl

转载自风宇冲Unity3D教程学院

Twirl是一个全屏画面扭曲的效果,新仙剑的战斗切换有用到这个效果。

主要有三个设置:

center  扭曲的中心点

radius 扭曲的范围

angle 扭曲的角度

用到了如下函数

Matrix4x4.TRS(Vector3 pos, Quaternion rotate,Vector3 scale)

创建一个包括位移,旋转,缩放的矩阵

Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, angle),Vector3.one);

然后通过material的以下函数向shader里传参数

material.SetMatrix("name",value)   对应Shader里的 float4x4

material.SetVector("name",value)  对应Shader里的 float4

float2 MultiplyUV (float4x4 mat, float2 inUV) {

  float4 temp = float4 (inUV.x, inUV.y, 0, 0);

  temp = mul (mat, temp);

  return temp.xy;

}

步骤:

脚本

(1) 通过Angle得到旋转矩阵

Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0 , 0 , angle),Vector3.one);

(2) 将矩阵和 旋转中点 及 半径传入shader.

Shader

(1) 将坐标系从左下角的坐标系 转到 以旋转中点为 原点的坐标系

vert里 o.uv = v.texcoord - _CenterRadius.xy;

(2) 将旋转坐标系 里的uv乘以 旋转矩阵。

(3) 将uv除以 半径, 再取长度。长度超过1则为 旋转区域外,小于则在区域内

(4) 如果在区域外,则为默认offset, 在内则是旋转后的offset

脚本

using UnityEngine;
using System.Collections;
public class TwirlEffectMe : MonoBehaviour {
    public Shader shader;
    private Material mat;
    public Vector2  radius = new Vector2(0.3F,0.3F);
    public float    angle = 50;
    public Vector2  center = new Vector2 (0.5F, 0.5F);

    void Start()
    {
        mat = new Material(shader);
    }

    void OnRenderImage (RenderTexture source, RenderTexture destination) {
        RenderDistortion (mat, source, destination, angle, center, radius);
    }

    public static void RenderDistortion(Material material, RenderTexture source, RenderTexturedestination, float angle, Vector2 center, Vector2 radius)
    {
        Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0 , 0 , angle), Vector3.one);
        material.SetMatrix("_RotationMatrix", rotationMatrix);
        material.SetVector("_CenterRadius", new Vector4(center.x, center.y, radius.x, radius.y));
        Graphics.Blit(source, destination, material);
    }
}

  

Shader脚本

Shader "Custom/TwirlEffectMe" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            ZTest Always Cull Off ZWrite Off
            Fog { Mode off }

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            uniform sampler2D _MainTex;
            uniform float4 _MainTex_TexelSize;
            uniform float4 _CenterRadius;
            uniform float4x4 _RotationMatrix;

            struct v2f {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
            } ;

            v2f vert( appdata_img v )
            {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.texcoord - _CenterRadius.xy;
                return o;
            }

            float4 frag (v2f i) : COLOR
            {
                float2 offset = i.uv;
                float2 distortedOffset = MultiplyUV (_RotationMatrix, offset.xy);
                float2 tmp = offset / _CenterRadius.zw;
                float2 finalUV;
                float len = length(tmp);
                // out of twirl
                if( len >1)
                {
                    finalUV = offset;
                }
                else
                {
                    finalUV = distortedOffset;
                }
                // back to normal uv coordinate
                finalUV += _CenterRadius.xy;
                return tex2D(_MainTex, finalUV);
            }
            ENDCG
        }
    }
    Fallback off
}

  

但是运行后,发现仅仅是简单旋转。需要再加上模糊。

分析一下,发现是由内向外从distortedOffset 渐渐向 正常offset过度的过程

于是将43行的finalUV = distortedOffset;改为

finalUV = lerp(distortedOffset, offset, len );

整体代码如下:

Shader "Custom/TwirlEffectMe" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            ZTest Always Cull Off ZWrite Off
            Fog { Mode off }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            uniform sampler2D _MainTex;
            uniform float4 _MainTex_TexelSize;
            uniform float4 _CenterRadius;
            uniform float4x4 _RotationMatrix;

            struct v2f {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
            } ;

            v2f vert( appdata_img v )
            {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.texcoord - _CenterRadius.xy;
                return o;
            }
            float4 frag (v2f i) : COLOR
            {
                float2 offset = i.uv;
                float2 distortedOffset = MultiplyUV (_RotationMatrix, offset.xy);
                float2 tmp = offset / _CenterRadius.zw;
                float2 finalUV;
                float len = length(tmp);
                // out of twirl
                if( len >1)
                {
                    finalUV = offset;
                }
                else
                {
                    finalUV = lerp(distortedOffset, offset, len );
                }
                // back to normal uv coordinate
                finalUV += _CenterRadius.xy;
                return tex2D(_MainTex, finalUV);
            }
            ENDCG
        }
    }
    Fallback off
}

  

点击运行,效果对了。

时间: 2024-11-08 23:51:11

Unity3D教程宝典之Shader篇:第二十六讲ImageEffects_Twirl的相关文章

Unity3D教程宝典之Shader篇:第六讲TexGen

转载自风宇冲Unity3D教程学院 介绍 TexGen全称是Texture coordinate generation,即纹理坐标生成.本来模型的纹理坐标是在做模型的时候赋予各个顶点的.但是有时模型表面非常复杂,或者要做一些特效时,就需要其他方法来生成纹理坐标. TexGen主要用于Fixed Function Shader. 有如下模式ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal .  该函数直接对应OpenGL的tex

Unity3D教程宝典之Shader篇:第四讲制作一个美丽的地球

原创文章如需转载请注明:转载自风宇冲Unity3D教程学院 Vertex and Fragment Shader例子二,制作一个自动旋转的3D地球. 下载美丽的地球工程 原理是 2张贴图,一张地球图,一张云层分布图(1)通过uv.x即纹理坐标的横轴与时间相乘,产生球在移动的效果 (2)通过地球和云的颜色值叠加形成 层叠 的效果.注意:贴图的'Wrap Mode'属性一定要设置成Repeat                              关于Wrap Mode当Wrap Mode为Cl

Unity3D教程宝典之Shader篇:第八讲 Why CG?

转载自风宇冲Unity3D教程学院 Shader有Fixed Function, Vertex and Fragment, Surface, 而Vertex and Fragmen里又有CG和GLSL两种.为什么选CG做重点讲解呢? Fixed Function:老式的固定管线,实现功能有限,不必多说.CG:跨平台首选,Unity3d能直接把CG编译成GLSL.GLSL:支持Mac,iOS,安卓.不支持Windows.Unity3d不能把GLSL编译成CG.不适合广泛的跨平台.Surface:属

Unity3D教程宝典之Shader篇:第十一讲剔除及深度测试

转载自风宇冲Unity3D教程学院 Culling阴影面剔除 Culling阴影面剔除是一种优化技术.所有的多边形都有正反两面,而你永远只能看见其中一面,不信的话拿张纸板或者一面镜子看看你能不能同时看到两面.通常多边形面向屏幕里面的背面,我们看不见,所以会将该面剔除. Cull Off 关闭阴影面剔除 Cull Back 剔除背面 Cull Front 剔除正面 Depth Testing深度测试 Depth Testing:深度测试,也叫深度缓冲.只有最靠近观察者的物体会被绘制.深度即Z,该值

Unity3D教程宝典之Shader篇:第七讲流程图

转载自风宇冲Unity3D教程学院 步骤如图: 图一:坐标系变换图二:流水线图形图三:Unity3D渲染流程图四:光栅操作(又名光栅化操作) 图一:坐标系变换图二:流水线图形 图三:Unity3D渲染流程 图四:光栅操作

Unity3D教程宝典之Shader篇:第十七讲Heightmap与地形

转载自风宇冲Unity3D教程学院 Heightmap Heightmap, 高度图.通常Heightmap高度图储存成Gray Scale Image也就是常说灰度图.越白该点就越高,纯黑表示最低点,纯点表示最高点. 8位灰度图有256阶.16位灰度图有65536阶.如果依然精度不够用的话(例如绘制大型场景),那么可以使用标准的RGB位图来储存高度图,那么精度就是256的3次方=16777216阶.同理还可以再升为RGBA. Heightmap可以用3D软件(Unity的地形也可以)来绘制,或

Unity3D教程宝典之Shader篇:第十二讲 Alpha测试

转载自风宇冲Unity3D教程学院 引言:本讲和下一讲主要讲Alpha即透明通道有关的内容.RGBA,其中最终在屏幕上显示的只有RGB即 红绿蓝组成的颜色,Alpha并没有任何颜色显示.A只是辅助颜色运算特别是多图层运算而已.例如在单图层的情况下(1,1,1,0.8)输出的是(1,1,1)*0.8即 浅灰色(0.8,0.8,0.8),和(0.8,0.8,0.8)是等价的.但是假如不再是单图层而背景为绿色(0,1,0,1)的时候,(0.8,0.8,0.8)就不知道怎么去运算了,而(1,1,1,0.

Unity3D教程宝典之Shader篇

教程目录 基础讲:Shader学习方法基础讲:基础知识特别讲:常见问题解答特别讲:CG函数 第一讲: Shader总篇第二讲: Fixed Function Shader 第三讲: Vertex&Fragment Shader基础 第四讲: 制作一个美丽的地球第五讲:LOGO闪光效果 第六讲:TexGen第七讲:流程图第八讲:Why CG?第九讲:Render Path第十讲:雾化第十一讲:阴影面剔除及深度测试第十二讲:alpha测试第十三讲:alpha混合第十四讲:Surface Shader

Unity3D教程宝典之Shader篇:第二十讲法线贴图

转载自风宇冲Unity3D教程学院 上一讲我们讲了凹凸贴图以及生成法线贴图. 这一讲来谈谈怎么使用法线贴图. 一:法线贴图的原理 二:法线贴图的实现 三:法线贴图的使用 四:法线贴图的格式 一:法线贴图的原理 光照效果很大程度上是由垂直于物体表面的法线决定的,因为法线影响反射光的方向.均匀垂直的法线是镜面贴图.但是有时候我们会给一个平面使用砖墙贴图,砖墙应该是凹凸不平的,而如果让砖墙使用该平面的法线的话,画面就会很假,神马?一面墙像镜子一样反光=.= 而如果按真实砖墙去做模型的话,即做高精度模型

Unity3D教程宝典之Shader篇:第二十四讲Reflection Mapping

转载自风宇冲Unity3D教程学院 简介 Reflection Mapping,又叫Environment Mapping.对应TexGen的SphereMap和CubeReflect.是最快的reflect周围环境的算法 最早出现的是Sphere Mapping,之后被Cube Mapping取代.Reflection Mapping比射线追踪(Ray Tracing)高效得多 Reflection Mapping的前提是2个假设 (1)入射线来自无限距离 (2)物体是凸的,没有自身的相互反射