总结
基本操作
平铺和偏移
_Texture("Texture",2D)="white"{}
sampler2D _Texture;
float4 _Texture_ST;
o.uv=v.uv*_Texture_ST.xy+_Texture_ST.zw;
顶点坐标系MVP转换
float4 pos_world = mul(unity_ObjectToWorld, v.vertex);
float4 pos_view = mul(UNITY_MATRIX_V,pos_world);
float4 pos_clip = mul(UNITY_MATRIX_P,pos_view);
o.pos=pos_clip;
或者
o.pos=UnityObjectToClipPos(v.vertex);
CG变量用法
float = 32
half = 16
fixed =8
图像处理
面剔除
单独写死
Cull off
在面板上显示
[Enum(UnityEngine.Rendering.CullMode)]_CullMode("CullMode",Float)=2
Cull [_CullMode]
图片铺在模型上
图片将平铺到x与y组成的平面上
o.uv=v.vertex.xy*_Texture_ST.xy+_Texture_ST.zw;
xy变成yx时
相当与x轴旋转180度y轴旋转-90度
o.uv=v.vertex.yx*_Texture_ST.xy+_Texture_ST.zw;
float4 pos_world = mul(unity_ObjectToWorld, v.vertex);
加面解决圆面失真的问题
水波的制作
先制作动态圆盘
_Float("Float",Float)=0.0
_Vector("Vector",Vector)=(1,1,1,1)
_Texture("Texture",2D)="white"{}
half gradient=tex2D(_Texture,i.uv+_Time.y*_Vector.xy).x;
clip(gradient-_Float);
return gradient.xxxx;
噪声
_NoiseTex("NoiseTex",2D)="white"{}
half noise=1.0f-tex2D(_NoiseTex,i.uv+_Time.y*_Vector.wz).x;
clip(gradient-_Float-noise);
完善颜色,完整代码
Shader"MyShader/03shader"
{
Properties{
_Float("Float",Float)=0.0
_Range("Range",Range(0,1))=0.0
_Vector("Vector",Vector)=(1,1,1,1)
_Color("Color",Color)=(0.5,0.5,0.5,0.5)
_Texture("Texture",2D)="white"{}
_NoiseTex("NoiseTex",2D)="white"{}
[Enum(UnityEngine.Rendering.CullMode)]_CullMode("CullMode",Float)=2
}
SubShader{
Pass{
Cull [_CullMode]
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
struct appdata{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
sampler2D _Texture;
float4 _Texture_ST;
float _Float;
float4 _Vector;
sampler2D _NoiseTex;
float2 _NoiseTex_ST;
fixed4 _Color;
v2f vert(appdata v)
{
v2f o;
float4 pos_world = mul(unity_ObjectToWorld, v.vertex);
float4 pos_view = mul(UNITY_MATRIX_V,pos_world);
float4 pos_clip = mul(UNITY_MATRIX_P,pos_view);
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=v.uv.xy*_Texture_ST.xy+_Texture_ST.zw;
return o;
}
half4 frag(v2f i):SV_Target
{
half gradient=tex2D(_Texture,i.uv+_Time.y*_Vector.xy).x;
half noise=1.0f-tex2D(_NoiseTex,i.uv+_Time.y*_Vector.wz).x;
clip(gradient-_Float-noise);
return _Color;
}
ENDCG
}
}
}
半透明混合
参数意思
| one | 此输入的值是 one。该值用于使用源或目标的颜色的值。 |
---|
| Zero | 此输入的值是 zero。该值用于删除源或目标值。 | | SrcColor | GPU 将此输入的值乘以源颜色值。 | | SrcAlpha | GPU 将此输入的值乘以源 Alpha 值。 | | DstColor | GPU 将此输入的值乘以帧缓冲区的源颜色值。 | | DstAlpha | GPU 将此输入的值乘以帧缓冲区的源 Alpha 值。 | | OneMinusSrcColor | GPU 将此输入的值乘以(1 - 源颜色)。 | | OneMinusSrcAlpha | GPU 将此输入的值乘以(1 - 源 Alpha)。 | | OneMinusDstColor | GPU 将此输入的值乘以(1 - 目标颜色)。 | | OneMinusDstAlpha | GPU 将此输入的值乘以(1 - 目标 Alpha)。 |
常见混合类型
Blend SrcAlpha OneMinusSrcAlpha
Blend SrcAlpha One
Blend One OneMinusSrcAlpha
Blend One One
Blend OneMinusDstColor One
Blend DstColor Zero
Blend DstColor SrcColor
代码修改
Tags { "Queue" = "Transparent" }
ZWrite Off
Blend SrcAlpha One
half3 col=_Color.xyz*_Float;
half alpha=saturate(tex2D(_Texture,i.uv).r*_Color.a*_Float);
return half4(col,alpha);
边缘光(fresnel)简版的菲涅尔方程
菲涅尔边缘光实现
口述: 菲涅耳系数=pow (1.0f-saturate(dot(世界坐标到局部坐标的法线向量,世界坐标的顶点到摄像头的单位向量)) ,梯度系数)
o.normal_world=normalize( mul(float4(v.normal,0),unity_WorldToObject));
float4 pos_world = mul(unity_ObjectToWorld, v.vertex);
o.view_world=normalize(_WorldSpaceCameraPos.xyz-pos_world);
float3 normal_world=normalize(i.normal_world);
float3 view_world=normalize(i.view_world);
float NdotV=saturate(dot(normal_world,view_world));
half3 col=_Color.xyz*_Float;
float fresnel=pow(1.0f-NdotV,_Rim);
half alpha=saturate(_Float*fresnel);
return half4(col,alpha);
Pass{
ZWrite Off
Blend SrcAlpha One
Cull [_CullMode]
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
struct appdata{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 normal_world:TEXCOORD1;
float3 view_world:TEXCOORD2;
};
sampler2D _Texture;
float4 _Texture_ST;
fixed4 _Color;
float _Float;
float _Rim;
v2f vert(appdata v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.normal_world=normalize( mul(float4(v.normal,0),unity_WorldToObject));
float4 pos_world = mul(unity_ObjectToWorld, v.vertex);
o.view_world=normalize(_WorldSpaceCameraPos.xyz-pos_world);
o.uv=v.uv*_Texture_ST.xy+_Texture_ST.zw;
return o;
}
half4 frag(v2f i):SV_Target
{
float3 normal_world=normalize(i.normal_world);
float3 view_world=normalize(i.view_world);
float NdotV=saturate(dot(normal_world,view_world));
half3 col=_Color.xyz*_Float;
float fresnel=pow(1.0f-NdotV,_Rim);
half alpha=saturate(_Float*fresnel);
return half4(col,alpha);
}
预先写深度
修除内部透明小Bug,预先将前面的深度写入,但不写入颜色信息,用上面的pass第二遍时将后面的透明的给剔除掉,
Pass {
Cull Off
ZWrite On
ColorMask 0
CGPROGRAM
float4 _Color;
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return _Color;
}
ENDCG
}
|