5. Textures
27. A simple use of a texture image
27.1 how to add texture
_MainTex("Main Texture", 2D) = "white" {}
sampler2D _MainTex;
27.2 tex2d(sample2D,uv value)
color = tex2D(_MainTex,i.uv).rgb;
在_MainTex上找到对应的uv点进行采样,返回一个float4的颜色。
27.3 Rotate and aspect
- uv是指纹理上的坐标系,和纹理深度绑定
- 问题是:旋转导致,纹理上,y拉伸了
- 旋转之前,减小uv.y值,让纹理y方向拉伸
- 旋转之后,增大uv.y值,让纹理y方向压缩回去
27.4 Summary
- 纹理y轴拉伸
- 中心平移-纹理旋转
- 纹理y轴压缩
- 平移回去
- 去除超过1部分的uv
这里要说明,uv是可以超过[0,1]的,但是一般取值是[0,1],超过这个范围就有另一套算法,并不是不能超过
Shader "NiksShaders/Shader38Unlit"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float2 rotate(float theta,float2 pt,float aspect)
{
float c = cos(theta);
float s = sin(theta);
float2x2 mat = float2x2(c,-s,s,c);
//问题是:旋转之后,之前的y拉伸了,之后的y压缩了
pt.y /= aspect; //旋转之前,将y减小,即是拉伸成适合的长度
pt = mul(mat,pt);//旋转
pt.y *= aspect;//旋转之后再将y变大 即是 压缩
//为什么旋转之后,控制的值仍然是y,因为y存储的位置就没有变化,所以这个y依然控制图片上的y
//uv是指纹理上的坐标系,和纹理深度绑定
return pt;
}
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv:TEXCOORD0;
float4 position: TEXCOORD1;
};
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.position = v.vertex;
return o;
}
sampler2D _MainTex;
float4 frag (v2f i) : COLOR
{
float2 mirroruv = i.uv;
mirroruv.x = 1 - i.uv.x;
float2 center = 0.5;
i.uv = rotate(_Time.y,i.uv - center,2.0/1.5) +0.5;
fixed3 color;
//去除超出的部分
if(i.uv.x < 0||i.uv.x > 1||i.uv.y < 0|| i.uv.y>1)
{
color = 0;
}
else
{
color = tex2D(_MainTex,i.uv).rgb;
}
return fixed4( color, 1.0 );
}
ENDCG
}
}
}
28.Ripple the image
28.1 Using i.position
Using i.position.xy*2 the center of the screen is 0.
_Duration控制波动的速度,这里是越小波动越快
28.2 Choosing a different texel
波纹函数,从纹理上抓取另一部分的颜色。
float2 ripple = i.uv + pos/len*0.03*cos(len*12 -_Time.y*4);
28.3 Calculating delta
fmod(_Time.y,_Duration)
gives the remainder of_Time/_Duration
- sin function takes values in the range 0 to 2PI
- Multiply fmod value by 2pi/Duration to ensue correct range
28.4 Shader
float4 frag (v2f i) : COLOR
{
float2 pos = i.position.xy * 2;
float len = length(pos);
//从图片的另一个部分抓取一个颜色,这个是水波函数
float2 ripple = i.uv + pos/len*0.03*cos(len*12 -_Time.y*4);
float theta = fmod(_Time.y,_Duration)*(UNITY_TWO_PI/_Duration);//控制theta
float delta = (sin(theta) + 1.0)/2;//控制delta的范围从0到1
float2 uv = lerp(ripple,i.uv,delta);
fixed3 color = tex2D(_MainTex,uv).rgb;
return fixed4( color, 1.0 );
}
29. Blend between textures
29.1 Understanding the NextClicked function
If we click the next,then pic will change to next texture.
And a Change Effect.
float4 frag (v2f i) : COLOR
{
float time = _Time.y - _StartTime;//change time,点击时候设置目前时间为starttime
float2 p = -1.0 + 2.0 * i.uv;
float len = length(p);//这里是29.2说到的长度
float2 ripple = i.uv + (p/len)*cos(len*12.0-time*4.0)*0.03;
float delta = saturate(time/_Duration);
float2 uv = lerp(ripple, i.uv, delta);
fixed3 col1 = tex2D(_TextureA, uv).rgb;
fixed3 col2 = tex2D(_TextureB, uv).rgb;
//如果在之间就是过渡状态,在两边就是还没开始
float fade = smoothstep(delta*1.4, delta*2.5, len);
fixed3 color = lerp(col2, col1, fade);
return fixed4( color, 1.0 );
}
29.2 Creating the circular wipe(pos and uv)
将uv和pos对齐:
float2 p = -1.0 + 2.0 * i.uv;
这样就得到了(-1,1)的范围。
这时就能得到纹理uv对应到模型位置上,从而能够得到pos坐标系下的length(p)代表半径。
也就是这里是在操作纹理,所以需要一个将uv转换到pos,再去求每个位置是什么像素,从uv上面去取像素。
直接用pos的情况是,某个点的颜色是可以不通过纹理知道的。另外,如果直接通过tex2d将pos替换uv value也是可以的,但是这样就变得不可控了(tiling和offset没用了),所以应该让uv去适应pos。用pos来表示模型点的位置,uv来表示纹理的位置,让uv匹配到pos上。
29.3 Summary
- use the properties section to assign a texture,using the type 2D
- In the CGPROGRAM section give this a sample2D type
- Use the Cg function tex2D and a uv value to extract the level to use for the current pixel
- You can manipulate the UV value to give some amazing results.
29.4 Test
If we’re rotating a point by angle theta and c = cos(theta) and s = sin(theta). Which option would return a 2 x 2 rotation matrix?
——float2x2(c,s,-s,c)
If i.position * 2.0 gives values in the range -1 to 1, ie the center of the range is 0,0. Which answer would select a uv position on a line radiating from the center of the image and 0.1 further from the center than the uv value?
——float2 uv = i.uv + 0.1*i.position;
29.5 关于2D旋转矩阵Rotate
由于旋转矩阵是正交矩阵,且逆时针旋转为正。
所以,2D空间,逆时针旋转theta 的矩阵:
R
(
θ
)
=
(
c
o
s
s
i
n
−
s
i
n
c
o
s
)
R (\theta) = \begin{pmatrix} cos& sin\\ -sin& cos\\ \end{pmatrix}
R(θ)=(cos−sinsincos)
那么顺时针旋转就是-theta,所以矩阵是:
R
(
−
θ
)
=
(
c
o
s
−
s
i
n
s
i
n
c
o
s
)
R(-\theta) = \begin{pmatrix} cos& -sin\\ sin& cos\\ \end{pmatrix}
R(−θ)=(cossin−sincos)
这样也能得到
R
T
(
θ
)
=
R
(
−
θ
)
R^{T}(\theta) = R(-\theta)
RT(θ)=R(−θ)