一些通过uv纹理坐标实现的简单shader(上)

发表于2018-07-26
评论0 5.6k浏览
分两篇文章给大家介绍通过uv纹理坐标实现的简单shader,这篇先来说下如何实现简单的波动效果。

所谓纹理,简单说就是一张图片,通过规定好的原点和二维坐标(一般称为uv坐标),就可以获得图片任意像素的颜色信息。

三维建模时,为了控制模型外观,我们会通过纹理映射技术将图片“黏”在模型表面。在模型的每个顶点上,一般会存储一个 二维坐标信息,其对应的就是纹理图片的uv坐标,通过这个坐标,就可以确定每个顶点的颜色。当然,也可以通过纹理图片的像素存储其他信息,比如 模型顶点的法线等。

一般而言,为了显示正确的效果,模型顶点存储的uv坐标确定的而通过改变uv的值,我们就能够做出一些简单的效果,下面就来演示一个很常见波纹效果,其效果如下:

我们使用的是unity的顶点与片段着色器,首先是一些准备工作,如下:
Shader "Custom/Ripple" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            sampler2D _MainTex;
            float4 _MainTex_ST;
            struct v2f
            {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
            };
            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }
            float4 frag(v2f i) : COLOR
            {      
               //to do something
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

为了得到上图的效果,我们需要在片段着色器中对uv做相应的处理。 先看图, 想要产生这种类似于水面的波动效果,最简单的就是让图片的每一个像素沿着某个方向周期性的往复运动, 像下面这样:这种运动可以通过平面简谐波进行模拟,其波函数我们简写为y=Acos(at+bx),其中t为时间,x为与原点(已知振动方程的点)的距离。在我们的shader中, t很容易用_Time[1]表示,距离我们可以取uv.x(即u相同让它有相同的运动),同时为了方便调整其他参数,我们先在Properties里添加如下定义:
          _Scale("Scale", Range(0,500.0)) = 3.0                                
        _Speed("Speed", Range(-50,50.0)) = 1.0
        _Identity("Identity",Range(50,100.0))=80

然后在片段着色器中做如下处理:
    float4 frag(v2f i) : COLOR
    {
        float4 o;
        half2 uv = i.uv;
        half r = uv.x;//sqrt(uv.x*uv.x + uv.y*uv.y);
        half z = cos(_Scale*r + _Time[1] * _Speed) /_Identity;
        o.rgb = tex2D(_MainTex, uv+ float2(z,0)).rgb;
        o.a =1;
        return o;
    }

运行,调整一下参数,可以得到下面这样的效果, 可以清晰的感觉到像素在沿着x轴进行波动。

当然,为了效果好一点,我们可以作如下修改:
    void surf(Input IN, inout SurfaceOutput o) {
        half2 uv = IN.uv_MainTex;
        half r =sqrt(uv.x*uv.x + uv.y*uv.y);
        half z = cos(_Scale*r+_Time[1] * _Speed)/80;
        o.Albedo = _Color.rgb * tex2D(_MainTex, IN.uv_MainTex + float2(z,z)).rgb;
        o.Alpha = _Color.a;
    }

这里像素会沿着原点与该点的向量方向进行往复运动,因此与原点距离相同的圆上的点都有着相似的运动,其效果如下:
来自:https://blog.csdn.net/dark00800/article/details/58640983

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引