- 上一个笔记补充:Pass{[Name and tags][RenderSetup][TextureSetup]}
TextureSetup主要针对的是顶点着色器。
- Shader要求:
最终输出一张半透明面片;面片颜色可调;正反面均可显示。
Shader "Custom/Simple"
{
Properties
{
_Color("Base Color",Color)=(1,1,1,1)//颜色控制
_MainTex("Base(RGB)",2D)="white"{}//输入一张半透明的贴图
}
SubShader
{
tags{"Queue"="Transparent""RenderType"="Transparent""IgnoreProjector"="True"}//透明物体渲染顺序、渲染模式、忽略投影
Blend SrcAlpha OneMinusSrcAlpha //渲染状态 混合模式 SrcAlpha+OneMinusSrcAlpha=1 SrcAlpha混合因子
Pass
{
Name "Simple"
Cull off//正反面都显示
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _Color;
struct v2f//从顶点到片段过度的结构体
{
float4 pos:POSITION;
float4 uv:TEXCOORD0;
};//结构体后面要有分号
v2f vert(appdata_base v)//获取的是物体坐标系
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//模型坐标系、观察坐标系、投影坐标系变换矩阵相乘=MVP?最后得到的结果是投影坐标系
o.uv=v.texcoord;
return o;
}
half4 frag(v2f i):COLOR
{
half4 c=tex2D(_MainTex,i.uv.xy)*_Color;//纹理影射
return c;
}
ENDCG
}
}
}
- 效果:
- normal 值在1到-1之间 只有xyz三个值
normal数据转为颜色数据时的操作:
- 效果:
- 如果使贴图*法线颜色
frac(); 取小数位
saturate(x) 如果x小于0,返回0 ,如果大于1,返回1,否则,返回x。
any() 当前值是否非0 是的话 返回true。
- 功能扩充:
使得上例中的透明面片可以旋转,可以控制旋转速度。
Shader "Custom/Simple"
{
Properties
{
_Color("Base Color",Color)=(1,1,1,1)//颜色控制
_MainTex("Base(RGB)",2D)="white"{}//输入一张半透明的贴图
_RSpeed("RotateSpeed",Range(1,100))=30//设置旋转速度
}
SubShader
{
tags{"Queue"="Transparent""RenderType"="Transparent""IgnoreProjector"="True"}//透明物体渲染顺序、渲染模式、忽略投影
Blend SrcAlpha OneMinusSrcAlpha //渲染状态 混合模式 SrcAlpha+OneMinusSrcAlpha=1 SrcAlpha混合因子
Pass
{
Name "Simple"
Cull off//正反面都显示
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _Color;
float _RSpeed;
struct v2f//从顶点到片段过度的结构体
{
float4 pos:POSITION;
float4 uv:TEXCOORD0;
};//结构体后面要有分号
v2f vert(appdata_base v)//获取的是物体坐标系
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//模型坐标系、观察坐标系、投影坐标系变换矩阵相乘=MVP?最后得到的结果是投影坐标系
o.uv=v.texcoord;
return o;
}
half4 frag(v2f i):COLOR
{
float2 uv=i.uv.xy-float2(0.5,0.5);
float2 rotate=float2(cos(_RSpeed*_Time.x),sin(_RSpeed*_Time.x));
uv=float2(uv.x*rotate.x-uv.y*rotate.y,uv.x*rotate.y+uv.y*rotate.x);
uv+=float2(0.5,0.5);
half4 c=tex2D(_MainTex,uv)*_Color;//纹理影射
return c;
}
ENDCG
}
}
}
- uv坐标的范围是0到1,相当于把3D图形展开成2D面片。坐标系中,左上角0,0 右下角1,1
- 2D向量的旋转原理 :将UV进行坐标变换
- 纹理寻址模式(解释为什么旋转时候边缘会有一些多余图片像素):
- 在贴图的设置里 Wrap Mode 分为 Repeat 和Clamp(如果贴图边界透明,则uv坐标系外都设置为透明)
Filter Mode 过滤模式
point(最近点) Bilinear(插值产生新像素图) Trilinear(三维线性插值)
- 贴图和画面的像素并不是一对一的关系
贴图缩小:贴图像素密度高,画面像素密度低,需要将多个贴图像素映射到同一个画面像素。如:
反过来是贴图放大:贴图像素密度低,画面像素密度高,需要将一个贴图像素映射到多个画面像素。
可能造成的问题:
- 解决方法:贴图采样 确定当有多个贴图像素可选时,采取什么样的方式选择像素进行贴图。
主要两种方法:1.最靠近的像素:Nearest-Point Sampling
2.线性插值:Linear Sampling(BiLinear Samling 二维线性采样) 会将最靠近的4个贴图像素进行线性插值, 计算一个新的像素图作为结果。(可以解决贴图放大的问题,但缩小问题依然存在)
解决贴图缩小时的采样锯齿问题,要使用新贴图结构:mip-map 根据分辨率(距离远近)来调用不同大小
(就是需要近处清晰的就调用大图,远处不需要那么清晰的,就调用小图)
- Mip-map的采样方式:
- 3维线性采样(消耗性能最大 效果最好):
- Aniso Level 各向异性等级 可以调整显示细节。
- _Time: x,y,z,w代表不同的时间变量