5.Textures

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拉伸了
    1. 旋转之前,减小uv.y值,让纹理y方向拉伸
    2. 旋转之后,增大uv.y值,让纹理y方向压缩回去

27.4 Summary

  1. 纹理y轴拉伸
  2. 中心平移-纹理旋转
  3. 纹理y轴压缩
  4. 平移回去
  5. 去除超过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 );
}

image-20220711180859761

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上。

image-20220711181531706

29.3 Summary

  1. use the properties section to assign a texture,using the type 2D
  2. In the CGPROGRAM section give this a sample2D type
  3. Use the Cg function tex2D and a uv value to extract the level to use for the current pixel
  4. 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(θ)=(cossinsincos)
那么顺时针旋转就是-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(θ)=(cossinsincos)
这样也能得到
R T ( θ ) = R ( − θ ) R^{T}(\theta) = R(-\theta) RT(θ)=R(θ)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值