您的位置:首页 > 其它

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

2017-03-05 21:59 531 查看
    所谓纹理,简单说就是一张图片,通过规定好的原点和二维坐标(一般称为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;
}


    这里像素会沿着原点与该点的向量方向进行往复运动,因此与原点距离相同的圆上的点都有着相似的运动,其效果如下:



ML
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: