Unity3D学习笔记(三十五):Shader着色器(2)- 顶点片元着色器

Alpha测试
AlphaTest Great:大于
AlphaTest Less:小于
AlphaTest Equal:等于
AlphaTest GEqual:大于等于
AlphaTest LEqual:小于等于
AlphaTest Never:全不渲染
AlphaTest Always:全部渲染
如果使用后两项的命名的情况下,比较后的数字项没有意义
 
AlphaTest 比较项 数字
AlphaTest Great 0.5 //表示只渲染alpha值大于0.5的部分
AlphaTest Less 0.5 //表示只渲染alpha值小于0.5的部分
 
混合命令
Blend SrcFactor DstFactor
SrcFactor DstFactor 可以的取值
One表示1
Zero表示0
SrcColor当前的颜色
DstColor已经存在的颜色
SrcAlpha当前的透明度
DstAlpha已经存在的颜色的透明度
OneMinusSrcColor当前的颜色取反向 1-SrcColor
OneMinusSrcAlpha当前的Alpha值取反向 1-SrcAlpha
OneMinusDstColor已经存在的颜色取反向 1-DstColor
OneMinusDstAlpha已经存在的颜色的透明度取反向 1-DstAlpha
 
最终颜色 = 新颜色 * SrcFactor + 旧颜色 * DstFactor
 
新颜色:即将写入到颜色缓冲区的颜色
旧颜色:已经在颜色缓冲区的颜色
 
颜色运算法则(不同于向量运算法则)
(r,g,b) * a = (r*a,g*a,b*a)
(r,g,b) * (x,y,z) = (r*x,g*y,b*z)
(r,g,b) + (x,y,z) = (r+x,g+y,b+z)
A - (r,g,b) = (a-x,a-y,a-z)
 
例如
Blend Zero One //仅仅显示背景的颜色,自身的效果不会显示
Blend One Zero //显示贴图的RGB颜色,即使有透明通道的部分也显示原色,不会透过去
Blend One One //贴图色与背景色叠加,没有透明通道处理,结果可能更趋近于(1,1,1)
Blend SrcAlpha Zero //没有透明通道部分显示的是贴图的原色,有透明通道0的部分,显示黑色,0.5部分更趋近于黑色
Blend SrcAlpha OneMinusSrcAlpha //最终颜色 = 新颜色 * 当前透明度 + 旧颜色 * (1 - 当前透明度),最常用的透明混合方式
Shader "Lesson/AlphaTest" {
Properties {
_Tex("纹理", 2D) = "white"{}
_Alpha("透明度", Range(,)) = }
SubShader {
Pass
{
//表示只渲染alpha值大于0.5的部分
AlphaTest Greater 0.5
AlphaTest Greater [_Alpha] //Blend SrcAlpha OneMinusSrcAlpha
Blend SrcAlpha zero SetTexture[_Tex]
{
Combine texture
}
}
}
FallBack "Diffuse"
}
 
Cg语言,详见PPT
 
顶点/片元着色器
核心:
顶点函数:
片元函数:
 
顶点函数在几何阶段,能从应用程序获取顶点信息。这些信息就是通过顶点函数的参数传递进来的。顶点函数的返回值就是传递到片元函数里的,片元函数也是通过参数去接收的
Float4 vertex:顶点坐标(模型空间下)
Float4 normal:顶点的法线向量
Float4 tangent:顶点的切线向量
Float4 texcoord:第一UV颜色
Float4 texcoord1:第二UV颜色
Float4 color:顶点颜色
 
语义:语句的含义
顶点函数的形参后跟的语义:表示该形参的是接收应用程序传递来的是什么。
对于顶点函数的方法后跟的语义:修饰的返回值,代表该返回值表示的是什么。
对于片元函数的方法后跟的语义:修饰的是片元函数的返回值,代表的是告诉应该GPU是什么
 
从应用程序阶段到顶点函数阶段
1.POSITION:表示应用程序把顶点坐标传递过来并且存储在修饰的参数
2.NORMAL:表示法线,通常是float3
3TANGENT:表示切线
4.TEXCOORD0-N:从第1套UV到第7套UV
5.COLOR:顶点颜色
 
从顶点函数到片元函数能表示的语义
1.SV_POSITION:代表转换之后的齐次空间坐标
2.COLOR0:代表一组颜色
2.COLOR1:代表一组颜色
4.TEXCOORD0-N:从第1套UV到第7套UV
 
从片元函数输出的语义
SV_Target:输出的值会渲染到屏幕上
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFColor" {
Properties {
_Color("颜色", Color) = (,,,)
}
SubShader { //1.顶点片元程序也要写在Pass块里
Pass
{
//2.把Cg语言的开始和结束写出来
//表示Cg语言程序的开始
CGPROGRAM
//3.定义顶点函数和片元函数的名字
//#pragma 不变 vertex 关键字,后跟的是顶点函数的名字,vert顶点函数的名字
#pragma vertex vert //定义函数名为vert的函数为顶点函数
//#pragma 不变 fragment 关键字
#pragma fragment frag //定义函数名为frag的函数为片元函数
fixed4 _Color;//如果要在Cg语言中去使用属性面板定义的一些变量,需要在Cg语言中进行重定义
//4.实现顶点函数
//POSITION修饰的是顶点函数参数vet,证明vet是顶点坐标
//SV_POSITION修饰的是vet函数的返回值,证明返回值是转换之后的坐标
float4 vert(float4 vet : POSITION, float3 normal : NORMAL) : SV_POSITION
{
//顶点函数的核心作用必须做的是空间坐标转换
//mul是Cg语言的提供的API,计算向量与矩阵相乘
float4 position = UnityObjectToClipPos(vet); //
return position;
}
//5.实现片元函数
fixed4 frag() : SV_Target
{
//最重要的必须的做到就是返回一个颜色
return _Color;
}
//表示Cg语言程序的结束
ENDCG
}
}
FallBack "Diffuse"
}
Unity\Editor\Data\CGIncludes\UnityShaderUtilities.cginc里的UnityObjectToClipPos()函数
UnityCG.cginc常用的API
#ifndef UNITY_SHADER_UTILITIES_INCLUDED
#define UNITY_SHADER_UTILITIES_INCLUDED
// This file is always included in all unity shaders.
#include "UnityShaderVariables.cginc"
// Tranforms position from object to homogenous space
inline float4 UnityObjectToClipPos(in float3 pos)
{
// More efficient than computing M*VP matrix product
return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
}
inline float4 UnityObjectToClipPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
{
return UnityObjectToClipPos(pos.xyz);
}
#endif
 
UNITY_MATRIX_MVP的MVP是几何阶段的三次转变
M模型到世界
V世界到观察
P观察到剪裁
Unity3D学习笔记(三十五):Shader着色器(2)- 顶点片元着色器
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFNormal" {
Properties {
}
SubShader {
Pass
{
CGPROGRAM #pragma vertex vert
#pragma fragment frag
//定义一个结构体,作为顶点函数的参数
struct m2v
{
float4 vex : POSITION;//告诉应用程序把模型空间下的顶点坐标放在这
float3 normal : NORMAL;//告诉应用程序把模型空间下的法线放在这
float3 tangent : TANGENT;//告诉应用程序把模型空间下的切线放在这
};
//定义一个结构体,作为顶点函数的返回值和片元函数的参数
struct v2f
{
float4 position : SV_POSITION;//转换之后的顶点坐标
float3 normal : COLOR0;//法线
float3 tangent : COLOR1;//切线
};
//结构体作为参数和返回值
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex); //必须变换顶点坐标
f.normal = v.normal;//法线赋值
f.normal = mul(UNITY_MATRIX_M, v.normal);
//f.tangent = v.tangent;//切线赋值
return f;
}
fixed4 frag(v2f f) : SV_Target
{
return fixed4(f.normal.x, f.normal.y, f.normal.z, );//把法线作为颜色输出
//return fixed4(f.tangent.x, f.tangent.y, f.tangent.z, 1);//把切线作为颜色输出
}
ENDCG
}
}
FallBack "Diffuse"
}

UV坐标,可以通过顶点的UV坐标去获取纹理对应的颜色。对于图片的纹理来说UV的(0,0)点在左下角,UV的(1,1)点在右上角

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFTexture" {
Properties{
//定义一个图片
_MainTex("纹理", 2D) = "white"{}
}
SubShader{
//透明的纹理处理要把渲染队列调高
Tags{ "Queue" = "Transparent" }
Pass
{
//Cull off
//处理带有透明通道贴图的混合
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//重定义纹理
sampler2D _MainTex; //定义结构体,作为顶点函数的参数
struct m2v
{
float4 vex : POSITION;
float2 uv : TEXCOORD0;//告诉应用程序要UV信息
}; //定义一个结构体,作为顶点函数的返回值和片元函数的参数
struct v2f
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
}; v2f vert(m2v v)
{
v2f f;
//转换顶点坐标
f.position = UnityObjectToClipPos(v.vex);
f.uv = v.uv;
return f;
} fixed4 frag(v2f f) : SV_Target
{
//通过顶点的uv坐标去访问纹理对应的颜色
fixed4 color = tex2D(_MainTex, f.uv);
//return fixed4(f.uv.x,f.uv.y, 0, 1);
return color;
}
ENDCG
}
}
FallBack "Diffuse"
}
属性面板的变量,如果想在Cg程序中去使用,必须在Cg程序中重新定义:
Color - fixed4或float4
Vector - float4
Float - float
Range - float
2D - sampler2D
Rect - samplerRect
Cube - samplerCube
 
裁剪可以做场景切换的幕布效果
Unity3D学习笔记(三十五):Shader着色器(2)- 顶点片元着色器
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFDiscard" {
Properties{
_MainTex("纹理", 2D) = "white"{}
_Radius("半径", Range(, 0.75)) =
}
SubShader{
Pass
{
CGPROGRAM #pragma vertex vert
#pragma fragment frag sampler2D _MainTex;
float _Radius; struct m2v
{
float4 vex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
}; v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
f.uv = v.uv;
return f;
} fixed4 frag(v2f f) : SV_Target
{
//discard;//裁剪命令
fixed4 color = tex2D(_MainTex, f.uv); //0.2圆的半径
//圆心是0.5 0.5
float2 current = f.uv;
float2 center = float2(0.5, 0.5); float dis = pow((current.x - center.x), ) + pow((current.y - center.y), ); if (dis < pow(_Radius, ))
{
//在圆内
discard;
} return color;
}
ENDCG
}
}
FallBack "Diffuse"
}
 
Emission,类似RawImage的UV Rect
----Tiling:图片的左右偏移
----Offset:图片的大小比例
 
练习 - 实现西瓜的效果
Unity3D学习笔记(三十五):Shader着色器(2)- 顶点片元着色器
Shader "Lesson/VFWatermelon" {
Properties {
_LightColor("浅色条纹", Color) = (,,,)
_DarkColor("深色条纹", Color) = (,,,)
_Number("深色条纹数量", int) =
_Width("深色条纹宽度", Range(0.01, 0.2)) = 0.02
}
SubShader{
Pass
{
CGPROGRAM fixed4 _LightColor;
fixed4 _DarkColor;
int _Number;
float _Width;
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" struct m2v
{
float4 vex : POSITION;
float3 uv : TEXCOORD0;
}; struct v2f
{
float4 position : SV_POSITION;
float3 uv : TEXCOORD0;
}; v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
f.uv = v.uv;
return f;
} fixed4 frag(v2f f) : SV_Target
{
//实现1
//浅色条纹的宽度
float width = 1.0 / _Number - _Width;
for (int i = ; i < _Number; i++)
{
if (f.uv.x > i * (width + _Width) && f.uv.x < width + i * (width + _Width))
{
return _DarkColor;
}
}
return _LightColor;
/*
//实现2
//每对条纹的宽度(1深1浅)
float wid = 1.0 / _Number;
float x = fmod(f.uv.x, wid); //对wid取模(余)
if (x < _Width)
{
return _DarkColor;
}
return _LightColor;
*/
} ENDCG
}
}
FallBack "Diffuse"
}
上一篇:STL算法设计理念 - 函数适配器


下一篇:SQL Server索引进阶:第五级,包含列