http://edu.manew.com/course/96 //学习
顶点着色器主要是处理顶点的平移,缩放等位置或者大小相关的函数。
片段着色器主要处理的是像素的颜色。
任务2 : 三大主流语言
cg-->unity编译成--> glsl
任务3 : 图像硬件简史
任务4 : Unity shader的组织形式
SubShader --> 算法的选择
【fallback】 回滚,所有的shader失败时,用fallback来保障正确的显示
5. Fixed Function shader 固定管线功能的shader
pass命令 :
color() //()代表参数是一个固定值
color[] //[]代表一个参数值
Shader "Custom/ff_1" {
properties
{
//
_Color("Main Color",color)=(1,1,1,1)
_Ambient("Ambient",color)=(0.3,0.3,0.3,0.3)
_Specular("Specular",color)=(1,1,1,1)
_Shininess("Shininess",range(0,8))=6 //range 范围,可拖动的滑动块
_Emission("Emission",color)=(1,1,1,1) //取的类型是color
}
SubShader{
pass {
//color(1,0,0,1)
// color[_Color]
material
{
diffuse[_Color] //漫反射
ambient[_Ambient] //ambient 环境光
specular[_Specular] //镜面很光滑的物体
shininess[_Shininess] //高光反射的区域越集中 参数是一个浮点数
emission[_Emission] //自发光
}
lighting on
//如果使用了specular,则还需要开关
separatespecular on
}
}
}
6.
任务 11 :
Shader "Custom/vf" {
SubShader{
pass{
//至少有一个pass通道, 把pass通道里的代码段进行处理
//再shaderlab中要把这个带那段代码作为cg语言编译处理,则需要生命关键字:
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
#pragma exclude_renderers gles
//定制编译值类函数,定制的函数必须要编写,如果没有写pragarm,则默认使用target2.0
#pragma vertex vert //顶点着色器
#pragma fragment frag //片段着色器
typedef float4 FL4; //定义类型别名和c语言一样
#define MACROFL FL4(0,0,1,1); //宏定义
struct v2f //结构体定义
{
float4 pos;
float2 uv;
};
// //传进来的是一个模型当中的顶点数据,输出一个变量必须是float4 4阶的类型
// void vert(in float2 objPos:POSITION,out float4 pos:POSITION)
// {
// pos=float4(objPos,0,1);
// }
//
// //计算颜色
// void frag(out float4 col: COLOR)
// {
// col=float4(1,0,0,1);
// }
//传进来的是一个模型当中的顶点数据,输出一个变量必须是float4 4阶的类型
void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
{
pos=float4(objPos,0,1);
col=pos;
}
//计算颜色,传入颜色并且输出
void frag(inout float4 col: COLOR)
{
//float
//half //16进制 半精度
//fixed>fixed 基本类型 九位整数,对颜色的输出用fiexd来表示,真彩色
//变量可以定义在任何地方,只要使用之前定义
//int 多数情况按照float来处理的
//sampler*
//bool类型
col=float4(1,0,0,1); //向量的构造器
bool bl=false;
col=bl?col:fixed4(0,1,0,0);
//float
float2 fl2=float2(1,0);
float3 fl3=float3(1,0,1);
float4 fl4=float4(0,1,0,1);
//swizzle操作 ==>从某个数据向量中取分量,也可以颠倒分量的顺序 ,也可以重复
//取得时候xyz,rgb不能重复使用(xyz) (rgba)
float4 f1=float4(fl2.xy,0,1);
f1=float4(fl2.xx,1,1);
f1=float4(fl2.xy,fl4.ba);
FL4 f2=FL4(1,1,1,1);
f2=MACROFL;
//数据转换
col=f2; //宏定义测试
//矩阵
float2x2 M2x2={1,0,1,1}; //2行2列
float2x4 M2x4={ {0,0,1,1},{0,1,0,1} }; //2行4列 1,0,1,1 // 0,1,0,1
float2x4 M2x4_1={ fl4,{0,1,0,1} }; //2行4列 1,0,1,1 // 0,1,0,1
//矩阵不能改变量的值
col=M2x4_1[0]; //取第一行
//数组,不能swizzle操作
float arr[4]={1,0.5,0.5,1};
col=float4(arr[0],arr[1],arr[2],arr[3] );
//结构体的使用
v2f o;
o.pos=fl4;
o.uv=fl2;
}
ENDCG
}
}
}
12.Cg语言入门5流程控制
//switch在Cg中支持不好,模型中x的最小值-0.5,最大值 0.5,单位立方体
//循环控制语
//while的循环次数和显卡有关
Shader "Custom/vf11" {
SubShader {
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//传进来的是一个模型当中的顶点数据,输出一个变量必须是float4 4阶的类型
void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
{
pos=float4(objPos,0,1);
//Cg条件控制语句
if(pos.x<0&&pos.y<0) //红色
{
col=float4(1,0,0,1);
}
else if(pos.x<0)
{
col=float4(0,1,0,1);
}else if(pos.y>0)
{
col=float4(1,1,0,1);
}
else
{
col=float4(0,0,1,1);
}
}
//计算颜色,传入颜色并且输出
void frag(inout float4 col: COLOR)
{
//switch在Cg中支持不好,模型中x的最小值-0.5,最大值 0.5,单位立方体
//循环控制语句
int i=0;
while(i<10)
{
i++;
}
if(i==10)
{
col=float4(0,0,0,1);
}
i=0;
do
{
i++;
}while(i<10);
if(i==10)
{
col=float4(1,1,1,1);
}
for(i=0;i<1023;i++){}
if(i==1023)//显卡
{
col=float4(0.5,0.5,0,1);
}
}
ENDCG
}
}
FallBack "Diffuse"
}
13.Cg语言入门,Cg函数_1
代码的复用,函数的申明,函数参数都是值拷贝方式传递 ,或者使用out参数
Shader "Custom/vf2" {
Subshader{
pass{
CGPROGRAM
#pragma exclude_renderers d3d11 xbox360 gles
#pragma vertex vert
#pragma fragment frag
#include "Assets\sbin\sbin.cginc"
// void Func(out float4 c);
// float FunArr(float arr[2]);
void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
{
pos=float4(objPos,0,1);
col=pos;
}
void frag(inout float4 col:COLOR)
{
//Func(col);
float arr[]={0.5,0.5};
col.x=FunArr(arr) ;
}
//********************************************************************************
// //CG总是数据类型都是值拷贝,如果想有效,则使用out参数
// void Func(out float4 c)
// {
// c=float4(0,1,0,1);
// }
// //数组的传递
// float FunArr(float arr[2])
// {
// //初始化
// float num=0;
// for(int cow=0;cow<arr.Length;cow++)
// {
// num+=arr[cow];
// }
// return num;
// }
//**********************************************************************************
//代码的复用 .cginc//高亮
ENDCG
}
}
}
14.Cg语言入门,Cg函数_2
cg标准函数库 https://wenku.baidu.com/view/3a9db318fad6195f312ba675.html
数学函数
几何函数,距离判断,反射折射
纹理函数
导出函数
14.3D数学基础 1,坐标系
模型坐标系------各种矩阵变换-------->世界坐标系------视口变换--->摄像机坐标系----投影变换--》屏幕投影坐标系
(1).模型坐标系
(2)3D中的世界坐标系
(3)摄像机坐标系
(4)屏幕坐标系
做投影算法,3D模型透视投影
16. 3D数学基础:向量
4d向量,又叫齐次向量,主要是用在矩阵运算
(1)加法:对应分量分别相加
(2)减法 :对应分量分别相减
(3)和标量相乘,和分量分别相乘
(4)模长x平方+y平方,再开平方
(5)点积
Dot(v1,v2)=v1*v2=对应分量相乘再相加=一个变量值
可以计算两个向量的夹角
1--》0度
0.5--》60度
0--》90度 <90,则>0 =90,则=0 >90,则<0
计算1: 两个向量分量对应相乘再相加
(6)叉积
几何意义: 得到垂直向量
17 . 数学基础 矩阵
矩阵的维度和记法
矩阵的转置 :T表示转置
矩阵和标量的乘法 :每个元素分别相乘
矩阵和矩阵的乘法 :
规律:(1). 用第一个矩阵得第一行得每个分量和第二行得每一列的每个分量(然后再第二行),再相加
(2).交换位置,再转置,乘积是原来没有交换位置和转置的值
(3). 3行2列矩阵和3行3列矩阵不能相乘,要把3行2列矩阵做一下转置,转成2行3列的矩阵,再相乘
eg: 3*3矩阵乘以3*1列向量,则值是列向量
(4)单位矩阵,主对角线都是1,单位矩阵乘另一个矩阵,还是原来的矩阵。
18. 3D数学,矩阵和行列式
.矩阵和变换 2D旋转矩阵 3D旋转矩阵 c#顶点变换demo
(1) 2D旋转矩阵
19. 矩阵的逆
2D缩放矩阵
k是缩放因子,N 是向量
3D旋转矩阵,绕坐标轴旋转
参考: https://blog.csdn.net/haiying2016/article/details/77685459,描述的旋转后每个点对应的关系
3D缩放矩阵,绕任一个轴n进行缩放
缩放矩阵:
物体变换的组合:
P物体的每个顶点的位置 M变换矩阵
20. 矩阵和变换
向量扩展为3维的
透视投影:
21. 矩阵变换三维渲染—1
22. 矩阵变换三维渲染__2
23. 矩阵变换三维渲染__3
24. 矩阵变换三维渲染__4
方阵: 行数和列数相等,只有方阵的行列式有定义
2阶矩阵行列式: 主对角线是正,反对角线是负值
3阶方阵
3阶矩阵行列式: 主对角线和反对角线
代数余子式来计算n*n阶的行列式
n*n的行列式: 选随便一行中随便取四个数再*概该数的余子式
余子式是:取除掉这个数的行和列,剩下的数组成的矩阵就是这个数的余子式
系数的符号: (-1)i+j次方,i+j是行和列的系数,来判断是取正值还是取负数
完了后再按照3阶矩阵的余子式乘法
25. 矩阵变换三维渲染__5
矩阵的逆 逆的定义 计算 正交矩阵和它的逆
单位矩阵。它是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为1。除此以外全都为0。
行列式为0,则是奇异矩阵 ,没有逆矩阵 ,逆矩阵行列式不为0
标准伴随矩阵:http://edu.manew.com/course/96/task/1442/show
标准伴随矩阵过程: 先求原矩阵每个数的代数余子式,再转置
矩阵求逆: 伴随矩阵 / 该矩阵的行列式
逆矩阵*原矩阵=单位矩阵(单位矩阵:主对角线=1,其他都是0)
矩阵的逆: 用于撤销对图像的变换,投影变换是撤销不了的
正常计算矩阵的逆: 原矩阵的代数余子式矩阵-->转置--》伴随矩阵--》除以行列式,如果是正交矩阵,则不用
26. 矩阵变换三维渲染__6,矩阵的逆矩阵
27. 顶点数据的输入与输出 1
//vert顶点程序所有的输出必须要带一个语义,一个语义只能有一个输出(没有赋值不算输出,默认无效).
//frag程序使用POSITIO语义的变量,有且只有一个,顶点和片段 语义相同则就是同一个变量,和变量名无关
28. 顶点数据的输出和输出2,使用结构体对顶点的输出左包装
29. 更好的数据组织方式struct
30. Vertex Shader - Uniform 与 properties属性
31: Vertex Shader - 几何变换 —MVP矩阵变换 1
32 :Vertex Shader - 几何变换 —MVP矩阵变换 2
33: Vertex Shader - 几何变换 —顶点颜色变换 1
模型:x,y最小值是-0.5,最大值是 0.5
34: Vertex Shader - 几何变换 —顶点颜色变换 2
35:Vertex Shader - 几何变换 —顶点位移
Shader "Custom/vf35" {
properties
{
_R("R",range(0,5))=1
_OX("OX",range(-5,5))=0
}
SubShader
{
pass
{
//file:///D:/unity5.3.4/Editor/Data/Documentation/en/Manual/SL-UnityShaderVariables.html
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4x4 mvp;
float4x4 rm;
float4x4 sm;
float _R;
float _OX;
typedef struct v2f
{
//定义时把语义就指明
float4 pos:POSITION;
fixed4 col:COLOR;
}V2f;
//语义对应即可
//如果需要改变颜色时,可以使用屏幕坐标,来集中处理
//模型顶点位移的变化,在mvp之前处理变化
//基于物理的网格特性shader中没有的,shader只是改变的顶点的位置信息来显示
V2f vert(appdata_base v) //函数的返回语义
{
float4 wpos=mul(_Object2World,v.vertex);
float2 xy=wpos.xz; //取得是3维度的xz,范围
float d=_R-length(xy-float2(_OX,0)); //计算模长 /计算向量的模长sqrt( (xy.x-0)*(xy.x-0)+(xy.y-0)*(xy.y-0) ); //减圆心分量是0
d=d<0?0:d;
float height=1;
float4 uppos=float4(v.vertex.x,height*d,v.vertex.z,v.vertex.w);
V2f o;
o.pos=mul(UNITY_MATRIX_MVP,uppos); //矩阵乘法 得到得m*顶点
o.col=fixed4(uppos.y,uppos.y,uppos.y,1);
return o;
}
//frag程序使用POSITIO语义的变量,有且只有一个,顶点和片段 语义相同则就是同一个变量
fixed4 frag(V2f IN):COLOR
{
return IN.col;
}
ENDCG
}
}
}
36: Vertex Shader - 几何变换 —扭曲
Shader "Custom/vf36" {
SubShader
{
pass
{
//file:///D:/unity5.3.4/Editor/Data/Documentation/en/Manual/SL-UnityShaderVariables.html
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4x4 mvp;
float4x4 rm;
float4x4 sm;
float _R;
float _OX;
typedef struct v2f
{
//定义时把语义就指明
float4 pos:POSITION;
fixed4 col:COLOR;
}V2f;
//语义对应即可
//如果需要改变颜色时,可以使用屏幕坐标,来集中处理
//模型顶点位移的变化,在mvp之前处理变化
//基于物理的网格特性shader中没有的,shader只是改变的顶点的位置信息来显示
V2f vert(appdata_base v) //函数的返回语义
{
//弯曲变换
// float angle=length(v.vertex)*_SinTime.w; ////计算模长 /计算向量的模长sqrt( (xy.x-0)*(xy.x-0)+(xy.y-0)*(xy.y-0) ); //减圆心分量是0
//把顶点绕y轴旋转
// float4x4 m=
// {
// float4(cos(angle),0,sin(angle),0),
// float4(0,1,0,0),
// float4(-sin(angle),0,cos(angle),0),
// float4(0,0,0,1)
// };
//扭曲变换
float angle=v.vertex.z+_Time.w;
float4x4 m=
{
float4(sin(angle)/8+0.5,0,0,0),
float4(0,1,0,0),
float4(0,0,1,0),
float4(0,0,0,1)
};
//用投射到屏幕后的来影响矩阵m
v.vertex=mul(m,v.vertex);
V2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //矩阵乘法 得到得m*顶点
o.col=fixed4(0,1,1,1);
return o;
}
//frag程序使用POSITIO语义的变量,有且只有一个,顶点和片段 语义相同则就是同一个变量
fixed4 frag(V2f IN):COLOR
{
return IN.col;
}
ENDCG
}
}
}
37: Vertex Shader - 几何变换 —波
38:图形学入门 - 法向量与光照http://edu.manew.com/course/96/task/1550/show
(1) 光的向量的方向是相反的,一定是从模型的顶点指向光
(2)光的计算:需要两个向量,一个是法向量,一个是从顶点指向光源的向量
(3)两个向量规范化后,点积越小,光线越弱,判断法向量和视向量(camera)>90度,背对着,不可以显示
点积:
叉积:左手,四指从u指向v,大拇指的方向就是法向的方向,u*v得到向上的法向量,乘法顺序
叉积运算:
uV->叉积 法向量-->再和光向量点击
见图:
//因为我们是在xy平面上,所以判断z轴
var crossResult = Vector3.Cross(Vector3.up,p2-p1).z;
//Vector3.Cross(trans1.up, trans2.position - trans1.position).z; //transform的写法
Debug.Log("crossResult:" + crossResult);
39:基础实例 - C# 光照渲染 1//??
40:基础实例- C# 光照渲染 2
float dot;
bool cullBack;
/// <summary>
/// 计算三角形光照
/// </summary>
public void CalculateNormal(MatriX4x4 _Object2World,Vector4 _light)
{
//一: 物体到世界
this.Transform(_Object2World);
//二:法线向量叉乘
Vector4 U = this.b - this.a;
Vector4 V = this.c - this.a;
Vector4 normal= U.Cross(V); //法向量用U叉乘V
//三: 法线向量规范化后求点积,求点积的向量必须是规范化后的
dot = normal.Normalized.Dot(_light.Normalized);
dot = Math.Max(0, dot);
//背面光照剔除,法向量和视向量点积后,如果<0,则是背面,剔除
Vector4 E = new Vector4(0,0,-1,0);
cullBack = normal.Normalized.Dot(E) <0? true : false;
}
41:基础实例- C# 光照渲染 3
42:基础实例- C# 光照渲染 4
绘制cube,该面看的到,是顺时针绘制,看不到反时针
43:图形学入门 - 实现漫反射 Diffuse shader 1
tags{"LightMode"="ForwardBase"} //加这个标签就可以支持顶点光照
UNITY_LIGHTMODEL_AMBIENT环境光,必须要加,不然计算光照没有意义
#include "lighting.cginc"
点击的计算 法和光 向量必须是同一个坐标系中
44: 图形学入门 - 实现漫反射 Diffuse shader 2
V2f vert(appdata_base v) //函数的返回语义
{
V2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //矩阵乘法 得到得m*顶点
o.col=fixed4(0,0,1,1);
//v.normal=mul(_Object2World,v.normal);
float3 N= normalize(v.normal);
float3 L=normalize(_WorldSpaceLightPos0);
N=mul(float4(N,0),_World2Object); //交换参数传递顺序是转置矩阵 模型进行非等比例缩放后,用物体到模型的矩阵的逆矩阵的转置矩阵
N= normalize(N);
//N=mul(_Object2World,float4(N,0).xyz);
//L=mul(_World2Object,float4(L,0).xyz); //把光向量转到模型坐标系
float ndot1=saturate(dot(N,L) );//saturate 限定取得的值是0-1
o.col=_LightColor0*ndot1; //_LightColor0 光照射后的颜色
return o;
}
45:图形学入门 - 反射向量与Cg reflect函数
46:图形学入门 – 实现phong 光照
R=Reflect(I,N) //l是入射光 N是法线向量,是否是高亮
Shader "Custom/vf46" {
properties
{
_SpecularColor("SpecularColor",color)=(1,1,1,1)
_Shininess("Shininess",range(1,64)) = 8//衰减
}
SubShader
{
//file:///D:/unity5.3.4/Editor/Data/Documentation/en/Manual/SL-UnityShaderVariables.html
pass
{
//此处申明,什么通道,用什么函数
tags{"LightMode"="ForwardBase"} //加这个标签就可以支持顶点光照
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
#include "lighting.cginc"
float4 _SpecularColor;
float _Shininess;
typedef struct v2f
{
float4 pos:POSITION;
fixed4 col:COLOR;
}V2f;
V2f vert(appdata_base v) //函数的返回语义
{
V2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //矩阵乘法 得到得m*顶点
o.col=fixed4(0,0,1,1);
float3 N= normalize(v.normal);
//获取世界空间中的光的位置信息,并且归一化
float3 L=normalize(_WorldSpaceLightPos0);
//模型进行非等比例缩放后,用物体到模型的矩阵的逆矩阵(m->w或者w->m)的转置矩阵
N=mul(float4(N,0),_World2Object).xyz; //交换参数的传递顺序是转置矩阵
N= normalize(N);
float ndot1=saturate(dot(N,L) );//saturate 限定取得的值是0-1
o.col=_LightColor0*ndot1; //_LightColor0 光照射后的颜色
//wpos是世界空间中光的位置向量
//float3 wpos=mul(_Object2World,v.vertex).xyz;
//wpos -WorldSpaceLightPos0; 取反顶点到光源的方向
//照射点到光源的向量,慢反射光
float3 I=-WorldSpaceLightDir(v.vertex);
float3 R=reflect(I,N);
float3 V=WorldSpaceViewDir(v.vertex); //谁相机视向量
R=normalize(R);
V=normalize(V);
//镜面反射,光线是否全部进入到摄像机中
float specularScale=pow( saturate(dot(R,V)),_Shininess);//pow(,n) n次方,模拟衰减的幅度
o.col.rgb+=_SpecularColor*specularScale;
return o;
}
fixed4 frag(V2f IN):COLOR
{
return IN.col+UNITY_LIGHTMODEL_AMBIENT; //UNITY_LIGHTMODEL_AMBIENT环境光,必须要加,不然计算光照没有意义
}
ENDCG
}
}
}
47 . 图形学入门 - 半角向量与BlinnPhong——反射向量的原理
下图说明: 如果是单位向量,则Cos(N,L)=Dot(N,L)==>R 世界坐标
//光叠加使用->Phong模型
//BlinnPhong模型 没有使用点积
以下向量都是规范化向量
x,r都是单位向量的长度是1
BlinnPhong
入射光向量L和视向量求半角向量,半角向量和N法线求点积,先规范化后
48:Fragment shader - 片段级光照 1
顶点:基于顶点的,顶点的位置,缩放
片段:是基于像素的,颜色
漫反射:需要环境光
在顶点程序中处理光照和法线是不行的,因为每个顶点程序是把每个顶点并行来处理,在片段中一个三角面会使用同一个顶点的数据和法向量,在片段中基于原始的数据(顶点和法向量)来处理
光向量和法向量求点积,得到的是光线的强度,即光线入眼的多少。
49: Fragment shader - 片段级光照 2
50:Fragment shader - 片段级光照 3
阴影投射器: 创建的球体,如果使用5.0之后的标准着色器,则点光源必须是Soft Shadows,接收阴影
自己创建的shadow没有接收阴影,需要回滚到unity中检查看是否使用阴影投射器fallback "Diffuse"
51:Fragment shader - 片段颜色混合
(1)让自己的shader材质接收阴影
blend: 一个生成的颜色乘以原计数
52: Fragment shader - 边缘泛光shader 1
(1)设置shader的透明:
//需求:边缘地方很亮,不是边缘的很暗,
//摄像机看到这个物体,最边缘的顶点法线和摄像机视角夹角是90度,越暗,用点积来达到这种类似于边缘查找的效果
tags{"queue"="transparent"} //设置透明,渲染的顺序设置为transparent(透明)
blend srcalpha oneminussrcalpha //1-srcalpha(当前屏幕物体的阿尔法)
float bright=1.0-saturate( dot(N,V) ); //越暗则越亮: 点积的结果越大,越暗 法向量和视向量>90度,则越暗
zwrite off //写入深度的关闭,则透明物体之间没有遮挡
53: Fragment shader - 边缘泛光shader 2
54:Fragment shader - 片段级模型动态变色 1
55:Fragment shader - 片段级模型动态变色 2
if else 使用过多会导致机器硬件可能编译出错,是汇编语言
lerp(a,b,c)//用a*(1-c)+b*c
必须知道模型本地坐标最大最小数据是多少
Shader "Custom/vf54" {
properties
{
_MainColor("MainColor",color)=(1,1,1,1)
_SecondColor("SecondColor",color)=(1,1,1,1)
_Center("Center",range(-0.7,0.7))=0.2
_R("R",range(-0.5,0.5))=0
}
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4 _MainColor;
float4 _SecondColor;
float _Center;
float _R;
//顶点输出数据的结构体
struct v2f
{
float4 pos:POSITION;
float y:TEXCOORD0;//COLOR语义的变量会强制转正值
};
v2f vert(appdata_base v)
{
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.y=v.vertex.y;
return o;
}
fixed4 frag(v2f IN):COLOR
{
float d=IN.y-_Center; //润和的中心点 //0.3 0.2 0
float s=abs(d);
d=d/s;//正或负 -1<-->1
float f=s/_R; //接近润和点的润和比率
f=saturate(f); //限定在0-1,如>1,全部润和
d=d*f;
d=d/2+0.5;
return lerp(_MainColor,_SecondColor,d);
}
ENDCG
}
}
}
56: Fragment shader - 片段级模型动态变色 3
(1)求一个模型滋生坐标的最大最小值
Vector3[] vec1= mf1.mesh.vertices;
float max= vec1.Max (v=>v.x);
float min= vec1.Min (v=>v.x);
Debug.Log (max+" "+min);
(2)
表面shader是一个框架,编译时会自动带上语义,里面封装了完整的光的处理
让Surface Shader使用顶点着色器,插入编译指令
appdata_base //中只包含少了的顶点数据 appdata_full包含所有的的顶点数据
Albedo时影响材质的亮度
57: Fragment shader - 2D纹理采样 1
_MainTex的数据类型是sampler2D
DX11之前,2D纹理采样只能写在片段着色器中
设置:
WrapMode:图片导入模式设置为Repeat时,可以重复,则当U值是负值的时候,则会把图片拼接到左边
FilterMode(图像过滤模式):没有过滤时不会有颜色的重合计算,Biliner双线性过滤模式,Triliner三线性过滤模式,
U*512 获取的这个值得不到一个整数的时候,第一种就近采样,第二种Biliner,会找周围四个点(权重),得到这个颜色,
Triliner三线性过滤模式
采样: fixed4 col=tex2D(_MainTex,IN.uv);//采样函数
58:Fragment shader - 2D纹理采样 2
Tiling : x,y 表示再x和y放方向上平铺的数量
_MainTex_ST.xy+_MainTex_ST.zw //.xy 平铺 zw偏移
59:Fragment shader - 2D纹理采样 3
60. Fragment shader – UV动画 1
61:Fragment shader – UV动画 2_uv本身的改变
62:Fragment shader – UV动画 3
旋转时时,正视摄像机,则清晰,反之模糊
63: Fragment shader –纹理混合动画 1
创建动态背景,不使用粒子
cg种二维向量加float,则对每一位分量都加float
shader种过多使用sin和cos会使性能变慢,过多使用半透明回事性能变慢
64:Fragment shader –纹理混合动画 2 _两张纹理混合 _//alf半透明混合(增加性能) 多pass通道混合
66:纹理程序
66:Fragment shader – 程序纹理水波仿真1
67: Fragment shader – 程序纹理水波仿真2
1. 范围压缩: -1<--->1 0<---->1 ==》 0ffest_u/2*0.5f 0<--->1 -1<---->1 ==》 0ffest_u*2-1;
2.数组之间不要拷贝,使用交换引用的的方式
float[,] temp = waveA;
waveA = wavaB;
waveB = temp;
68.69
70: Fragment shader - Alpha 与 blend 运算 //对半透明物体额绘制
Zwrite off //不要进行深度写入,前提是深度测试ztest通过 使用透明或者不透明
71: Fragment shader 7 - 实现半透明着色 1 的制作,把zwirte关闭
效果: 角色: 一半处于透明。遮挡后处于高亮显示
72: Fragment shader 7 - 实现半透明着色 2 深度纹理采样
73:Fragment shader - 纹理法线与凹凸贴图 1
(1)凹凸映射 对法线进行编程 法线存在纹理中,再用纹理和光进行交互
74:Fragment shader - 纹理法线与凹凸贴图 2——从灰度到法线纹理,相邻灰度差
取出灰度值,构成高度差,图片要写入时用rgb32,使用压缩后再写入
75: Fragment shader - 纹理法线与凹凸贴图 3