您的位置:首页 > 移动开发 > Unity3D

Unity3d-Shader-UV移动

2016-04-03 22:18 281 查看
本文使用UV偏移,创建车道方向动画



原始素材



最终效果(带水平向移动)

Unity3d纹理坐标



偏移:Offset(xo,yo),将原点偏移到(xo,yo)。

平铺:Tiling(xt,yt),以偏移后的坐标为新原点,平铺(xt,yt)范围

Unity3d在创建Material,默认Offset = (0, 0),Tiling(1, 1)。即原点不偏移,平铺方向各1次。也就是原图显示。

Unity3d与OpenGl的纹理坐标同持一致。U方向从左到右,V方向从下到上。而DX U从左到右,V从上到下






Offset = (0, 0.5) Tiling = (0.5, 0.5)


Offset = (0.5, 0.5) Tiling = (0.5, 0.5)


Offset = (0, 0)Tiling = (0.5, 0.5)


Offset = (0.5, 0) Tiling = (0.5, 0.5)


Offset = (0, 0.5)Tiling = (1.0, 0.5)


Offset = (0, 0)Tiling = (1.0, 0.5)


Offset = (0, 0)Tiling = (0.5, 1)


Offset = (0.5, 0)Tiling = (0.5, 1)

GPU实现

了解纹理坐标后。接下来,我们将编写Shader实现车道方向动画。实现原理就是持续地修改贴图在U方向的偏移。(注意创建场景、GameObject、Material等基本操作不在此本文说明)。下面给出UV偏移的Shader代码。

Shader "Custom/UVOffset" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_USpeed("USpeed ", float) = 1.0
_UCount("UCount", float) = 1.0
_VSpeed("VSpeed", float) = 1.0
_VCount("VCount", float) = 1.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
#pragma surface surf Lambert

// 贴图
sampler2D _MainTex;

// U轴方向滚动速度
float _USpeed;
// U轴方向平铺个数
float _UCount;

// V轴方向滚动速度
float _VSpeed;
// V轴方向平铺个数
float _VCount;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
float2 uv = IN.uv_MainTex;
float detalTime = _Time.x;

//  计算X轴方向变化
uv.x += detalTime * _USpeed;
uv.x *=  _UCount;

// 计算Y轴方向变化
uv.y += detalTime * _VSpeed;
uv.y *= _VCount;

half4 c = tex2D (_MainTex, uv);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}


顶点纹理 = 时间 * 速度

即 uv.x += _Time.x * _USpeed 其中_Time是Unity3d内置变量。

NameTypeValue
_Timefloat4Time (t/20, t, t*2, t*3), use to animate things inside the shaders.
参考链接http://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

当前纹理(平铺)= 当前纹理 * 平铺个数

即 uv.x *= _UCount;

我们假设顶点范围[0,1],以U轴方向为例(顶点与纹理不是同一个东西

在_UCount = 1的情况下,uv.x = uv.x * 1,顶点与纹理一一对应。

在_UCount = 2的情况下,uv.x = uv.x * 2, 原本水平方向x = 0.5顶点,这次由于uv.x * 2,抽取了uv.x = 1.0的纹理(也可以说是uv.x = 0.0的纹理)。即相比于_UCount = 1,这次在顶点从开始x = 0.5,便重新以uv.x =0提取纹理。

CPU实现

为GPU计算的负担,可以将UV偏移的计算工作放到CPU中,最后将计算结果传回GPU渲染即可。下面是使用MonoBehaviour实现UV偏移代码。

主要使用到了Material.GetTextureOffsetSetTextureOffset对应纹理坐标Offset

Material.GetTextureScaleSetTextureScale对应纹理坐标Tiling

using UnityEngine;

public class UVOffset: MonoBehaviour {

// U轴方向滚动速度
public float USpeed = 1.0f;
// U轴方向平铺个数
public int UCount = 1;

// V轴方向滚动速度
public float VSpeed = 1.0f;
// V轴方向平铺个数
public int VCount = 1;

private Material mat = null;

private void Awake()
{
if (this.renderer != null)
this.mat = this.renderer.material;
}

private void Update()
{
if (this.mat == null)
return;

Vector2 offset = this.mat.GetTextureOffset("_MainTex");
Vector2 tiling  = this.mat.GetTextureScale("_MainTex");

offset.x += Time.deltaTime * USpeed;
offset.y += Time.deltaTime * VSpeed;
tiling.x = UCount;
tiling.y = VCount;

this.mat.SetTextureOffset("_MainTex", offset);
this.mat.SetTextureScale("_MainTex", tiling);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: