文章目录
- 前言
- 一、Tilling(缩放度),个人理解有点像减小周期函数的周期的效果(在单位空间内,容得下重复的函数图像的多少)
- 二、Offset(偏移度),个人理解是函数的平移
- 三、在Shader中使用 Tilling 和 Offset 时,需要在纹理后申明一个 四维向量(因为是纹理,需要精确一点,一般使用float4这个四维向量,且名字在贴图名后加 _ST 即可)
- 1、然后这里用消融效果的噪波贴图做例子,就是在片元着色器中,对噪波贴图进行采样时,使用噪波贴图的二维向量 uv * XX_ST.xy + XX_ST.zw (这里的xy代表Tilling的xy,zw代表Offset的xy)
- 2、优化代码
- 在片元着色器取样时,对每一个取样点都计算 缩放 和 偏移 对性能损耗较大,故在顶点着色器中进行该操作
前言
Unity中Shader 纹理属性 Tilling(重复度) 和 Offset(偏移度)
一、Tilling(缩放度),个人理解有点像减小周期函数的周期的效果(在单位空间内,容得下重复的函数图像的多少)
二、Offset(偏移度),个人理解是函数的平移
把 g 函数理解为 原贴图,f函数理解为 经过Tilling 和 Offset 后的贴图。
Tilling就是 图中 的 2 ,Offset就是图中的0.2
Tilling控制单位空间内,贴图可以重复几次,Offset控制贴图偏移多少
图形计算器网址:https://www.geogebra.org/graphing
三、在Shader中使用 Tilling 和 Offset 时,需要在纹理后申明一个 四维向量(因为是纹理,需要精确一点,一般使用float4这个四维向量,且名字在贴图名后加 _ST 即可)
1、然后这里用消融效果的噪波贴图做例子,就是在片元着色器中,对噪波贴图进行采样时,使用噪波贴图的二维向量 uv * XX_ST.xy + XX_ST.zw (这里的xy代表Tilling的xy,zw代表Offset的xy)
代码示例:
Shader "MyShader/P0_7_7"
{
Properties
{
//使用这个标签,可以使外部暴露属性,有标题
[Header(Base)]
[NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
_Clip("Clip",Range(0,1)) = 0
//使用这个标签可以 在两行暴露属性之间加 间隙
[Space(10)]
[Header(Dissolve)]
_DissolveTex("DissolveTex",2D) = "white"{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float _Clip;
sampler2D _DissolveTex;
//这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _ST
float4 _DissolveTex_ST;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//外部获取的 纹理 ,使用前都需要采样
fixed4 dissolve = tex2D(_DissolveTex,i.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw);
//片段的取舍
clip(dissolve.r - _Clip);
return col;
}
ENDCG
}
}
}
效果
2、优化代码
在片元着色器取样时,对每一个取样点都计算 缩放 和 偏移 对性能损耗较大,故在顶点着色器中进行该操作
改写后的代码:
Shader "MyShader/P0_7_7"
{
Properties
{
//使用这个标签,可以使外部暴露属性,有标题
[Header(Base)]
[NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
_Clip("Clip",Range(0,1)) = 0
//使用这个标签可以 在两行暴露属性之间加 间隙
[Space(10)]
[Header(Dissolve)]
_DissolveTex("DissolveTex",2D) = "white"{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float _Clip;
sampler2D _DissolveTex;
//这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _ST
float4 _DissolveTex_ST;
struct appdata
{
float4 vertex : POSITION;
float4 uv : TEXCOORD0;
};
struct v2f
{
float4 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//为了减少传入的值 ,所以就不创建新变量来存储,而是把 uv 改为 四维向量 来用
//使用 o.uv 的 xy 来存放 原人物贴图
//使用 o.uv 的 zw 来存放 噪波贴图缩放 和 偏移 后的值
o.uv.xy = v.uv.xy;
o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//外部获取的 纹理 ,使用前都需要采样
fixed4 dissolve = tex2D(_DissolveTex,i.uv.zw);
//片段的取舍
clip(dissolve.r - _Clip);
return col;
}
ENDCG
}
}
}
再次优化
Unityt提供额缩放和偏移的函数
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
来进行 o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;这步,所以替换为该函数
TRANSFORM_TEX(o.uv,_DissolveTex);
最终代码
Shader "MyShader/P0_7_7"
{
Properties
{
//使用这个标签,可以使外部暴露属性,有标题
[Header(Base)]
[NoScaleOffset]_MainTex ("Texture", 2D) = "white" {}
_Clip("Clip",Range(0,1)) = 0
//使用这个标签可以 在两行暴露属性之间加 间隙
[Space(10)]
[Header(Dissolve)]
_DissolveTex("DissolveTex",2D) = "white"{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float _Clip;
sampler2D _DissolveTex;
//这个四维向量,xyzw分别表示 Tilling 和 Offset 的 xy ,命名方式 在纹理名 后加 _ST
float4 _DissolveTex_ST;
struct appdata
{
float4 vertex : POSITION;
float4 uv : TEXCOORD0;
};
struct v2f
{
float4 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//为了减少传入的值 ,所以就不创建新变量来存储,而是把 uv 改为 四维向量 来用
//使用 o.uv 的 xy 来存放 原人物贴图
//使用 o.uv 的 zw 来存放 噪波贴图缩放 和 偏移 后的值
o.uv.xy = v.uv.xy;
o.uv.zw = v.uv * _DissolveTex_ST.xy + _DissolveTex_ST.zw;
o.uv.zw = TRANSFORM_TEX(o.uv,_DissolveTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//外部获取的 纹理 ,使用前都需要采样
fixed4 dissolve = tex2D(_DissolveTex,i.uv.zw);
//片段的取舍
clip(dissolve.r - _Clip);
return col;
}
ENDCG
}
}
}