Unity Shader学习笔记
一、网址
CG语言教程官网:https://docs.nvidia.com/
一些网站:https://www.shadertoy.com/
数学函数在线演示:https://zh.numberempire.com/graphingcalculator.php
各种空间和基本光照模型:http://blog.csdn.net/lyh916/article/details/50906272
切线空间:https://blog.csdn.net/bonchoix/article/details/8619624
二、UnityCG.cginc中一些常用的函数
// 摄像机方向(视角方向)
float3 WorldSpaceViewDir(float4 v) // 根据模型空间的定点坐标,得到(世界空间)从这个点到摄像机的观察方向
float3 UnityWorldSpaceViewDir(float4 v) // 世界空间中的顶点坐标==》世界空间从这个点到摄像机的观察方向
float3 ObjSpaceViewDir(float4 v) // 模型空间中的顶点坐标==》模型空间从这个点到摄像机的观察方向
// 光源方向
float3 WorldSpaceLightDir(float4 v) // 模型空间中的顶点坐标==》世界空间从这个点到光源的方向
float3 UnityWorldSpaceLightDir(float4 v) // 时间空间中的定点坐标==》世界空间中从这个点到光源的方向
float3 ObjSpaceLightDir(float4 v) //模型空间的顶点坐标==》模型空间中从这个点到光源的方向
// 方向转换
float3 UnityObjectToWorldNormal(float3 norm) // 把法线方向 模型空间==》世界空间
float3 UnityObjectToWorldDir(flaot3 dir) // 把方向 模型空间==》世界空间
float3 UnityWorldToObjectDir(float3 dir) // 把方向 世界空间==》模型空间
三、OpenGL和DirectX
1、OpenGL
多用于移动平台,使用GLSL shader语言
2、DirectX
使用HLSL shader语言
3、CG
使用CG编写的shader可以运行在OpenGL和DirectX上
四、Unity Shader的分类
使用的是ShaderLab编写Unity中的Shader
1、表面着色器 Surface Shader (Unity独有)
2、 顶点/片元着色器 Vertex/Fragment Shader
3、 固定函数着色器 Fixed Function Shader (被弃用)
五、Shader基本结构
Shader "Siki/01 myshader" // 这里指定shader的名字,不要求和文件名一致
{
Properties // 属性 面板显示
{
}
// SubShader 可以写很多个 显卡运行效果的时候,从第一个SubShader开始,如果第一个SubShader里面的效果多可以实现,那么就使用第一个SubShader,如果显卡发现这个SubShader里面某些效果实现不了,他会自动运行下一个SubShader
SubShader{
}
// 后备方案
Fallback "VertexLit"
}
六、属性类型,放到Properties中,在面板显示
_Color("Color",Color)=(1,1,1,1) // 属性名(显示名,类型)=默认值(r,g,b,a)
_Vector("Vector",Vector)=(1,2,3,4) // Vector是向量类型 4个向量
_Int("Int",Int)=34234 // 整数类型
_Float("Float",Float)=3.14 // 小数类型
_Range("Range",Range(1,11))=6 //小数类型 有限定,从1-11
_2D("Texture",2D) = "white"{} // 图片类型 如果不指定图片就显示white,也可以是其他颜色(red等)
_Cube("Cube",Cube)= "white"{} // 立方体纹理
_3D("Texture",3D)="black"{} // 3D ?
七、语义
1、用应用程序传递到顶点函数的语义有哪些a2v
POSITION 顶点坐标(模型空间下的)
NORMAL 法线(模型空间下的)
TANGENT 切线(模型空间)
TEXCOORD0 ~ n 纹理坐标
COLOR 顶点颜色
2、从顶点函数传递给片元函数的时候可以使用的语义
SV_POSITION 剪裁空间中的顶点坐标(一般是系统直接使用)
COLOR0 用于数据传递,可以传递一组值(4个值)
COLOR1 用于数据传递,可以传递一组值(4个值)
TEXCOORD0 ~ 7 传递纹理坐标
3、片元函数传递给系统
SV_Target 颜色值,显示到屏幕上的颜色
八、光照模型
光照模型就是一个公式,使用这个公式来计算在某个点的光照效果
1、标准光照模型
在标准光照模型里面,我们把进入摄像机的光分为下面四个部分
1)自发光
2)高光反射 Specular = 直射光 * pow(max(cosθ,0),高光的参数) θ:夹角,是反射光方向和视野方向的夹角 高光的参数越大高光范围越小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4WrZWNK-1669789482938)(images/高光反射.png)]
pow(x,y) // x的y次方
// Blinn 光照模型
Specular = 直射光 * pow(max(cosθ,0),高光的参数) // θ:夹角,是反射光方向和视野方向的夹角
// Blinn-Phong 光照模型
Specular = 直射光 * pow(max(cosθ,0),高光的参数) // θ:夹角,是法线和x的夹角 x 是视野方向和平行光方向的平分线
3)漫反射 Diffuse = 直射光颜色 * max(0,cos夹角(光和法线的夹角)) cosθ = 光方向 · 法线方向
Tags{"LightMode"="ForwardBase"} // 只有定义了正确的LightMode才能得到一些Unity的内置光照变量
#include "Lighting.cginc" // 包含unity的内置的文件,才可以使用unity内置的一些变量
normalize() // 用来把一个向量,单位化(原来方向保持不变,长度变为1)
max() // 用来取得函数中最大的一个
dot // 用来取得两个向量的点积
_WorldSpaceLightPos0 // 取得平行光的位置
_LightColor0 // 取得平行光的颜色
UNITY_MATRIX_MVP // 这个矩阵用来把一个坐标从模型空间转换到剪裁空间
_World2Object // 这个矩阵用来把一个方向从世界空间转换到模型空间
// 半兰伯特光照模型
Diffuse = 直射光颜色 * (cosθ*0.5*0.5) // 1-0之间 被光明也不会全黑了
// 兰伯特光照模型
Diffuse = 直射光颜色 * max(0,cos夹角(光和法线的夹角))
4)环境光
UNITY_LIGHTMODEL_AMBIENT // 用来获取环境光
九、纹理贴图
法线贴图
颜色值处理 pixel = (normal + 1)/2
normal = pixel*2-1