- 本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载。
- 本篇博客会补充一些扩展内容(例如其他博客链接)。
- 本篇博客还会提供一些边读边做的效果截图。文章内所有数学公式都由Latex在线编辑器生成。
- 本篇博客主要提供一个“glance”,知识点的总结。如有需要请到书店购买正版。
- 博客提及所有官方文档基于2022.2版本,博客会更新一些书中的旧的知识点到2022.2版本。
- 如有不对之处欢迎指正。
- 我创建了一个游戏制作交流群:637959304 进群密码:(CSGO的拆包密码)欢迎各位大佬一起学习交流,不限于任何平台(U3D、UE、COCO2dx、GamesMaker等),以及欢迎编程,美术,音乐等游戏相关的任何人员一起进群学习交流。
- 初级篇内容主要讲述关于基础的光照模型、纹理和透视等的初级渲染效果。(这部分也可以同时阅读我的HLSL博客内容进行学习)
UnityShader入门
- 最简单的顶点/片元着色器:
Shader "name"
{
Properties
{
//属性
}
SubShader
{
Pass
{
//设置渲染状态和标签
//开始CG代码片段
CGPROGRAM
//编译指令
#pragma vertex vert
#pragma fragment frag
//CG代码
ENDCG
//其他设置
}
//其他pass
}
//其他的SubShader
//如果SubShader都失败了
Fallback “VertexLit”
}
- 第一个代码
- 关于’:’语法,可以理解为一种限制,或条件。例如: SV_POSITION是限制函数只能输出裁剪空间的坐标,也可以换一种角度理解,限制->通知,告知Unity要输出的是裁剪空间坐标。
shader "Example/Shader01"
{
SubShader
{
Pass
{
//CG代码片段
CGPROGRAM
//告诉Unity哪个函数包含了顶点着色器代码,哪个函数包含片元着色器代码
#pragma vertex vert
#pragma fragment frag
//POSITION把顶点坐标填入到V中,SV_POSITION顶点着色器输出的是裁剪空间中的坐标
float4 vert(float 4 v : POSITION) : SV_POSITION
{
return mul (UNITY_MATRIX_MVP,v);
}
fixed4 frag() : SV_Target
{
return fixed4(1.0,1.0,1.0,1.0);
}
ENDCG
}
}
}
材质,Shader
游戏内物体(CUBE)
效果
- 活学活用: return fixed4(1.0,1.0,0.5,1.0);时的效果。有时候要刷新一下材质才能显示出效果。
- 注意有一条语句语法进行了更新:Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)’ with ‘UnityObjectToClipPos(*)’
- 我们利用结构体来存储模型的法线,纹理坐标等信息。
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//输入结构体
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
//输出结构体
struct v2f
{
//裁剪信息
float4 pos : SV_POSITION;
//颜色信息
fixed3 color : COLOR0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex.xyz);
//根据法线向量v.normal来改变颜色
o.color = v.normal * 0.5 fixed3(0.5,0.5,0.5);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
你别说还蛮好看的
- 属性设置:设置一个颜色的properties让用户自定义颜色。
shader "Example/Shader01"
{
//自定义用户面板
Properties
{
_Color ("Color Tint",Color) = (1.0,1.0,1.0,1.0)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex.xyz);
o.color = v.normal * 0.5 fixed3(0.5,0.5,0.5);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed3 c = i.color;
//让用户面板中的颜色来决定顶点输出的颜色
c *= _Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
- ShaderLab属性类型和CG变量类型的匹配关系
ShaderLab属性类型 | CG变量类型 |
---|---|
Color,Vector | float4,half4,fixed4 |
Range,Float | float,half,fixed |
2D | sampler2D |
Cube | samplerCube |
3D | sampler3D |
- 数值类型:精度范围在不同平台可能会略有不同
类型 | 精度 |
---|---|
float | 32位 |
half | 16位,范围: -60 000 |
fixed | 11位,范围: -2.0 |
- Unity内置文件和变量:传送门,UnityShader提供了一些内置文件(具体见官方手册),可以不适用include进行头文件包含,Unity会自动加安策处理。
- 内置着色器变量:传送门
- CG/HLSL语义:语义可以让Shader知道从哪里读取数据(例如:COLOR0)。即使语义相同,位置不同表达的意思也会不同。DirectX10以后新的语义类型:系统数值语义(system-value semantics),以SV为开头,代表系统数值。有些时候(例如POSITION和SV_POSITION)语义可以不加SV开头,但如果考虑跨平台的工程,那么最好在能加SV的地方把SV加上去。
- 从应用阶段传递模型数据给顶点着色器时的常用语义:
语义 | 描述 |
---|---|
POSITION | 模型空间顶点位置,float4 |
NORAML | 顶点法线,float3 |
TANGENT | 顶点切线,float4 |
TEXCOORD0-7 | 寄存器类似于,存放坐标等。float2或float4 |
COLOR | 顶点颜色,fixed4或float4 |
- 从顶点着色器传递数据给片元着色器时的常用语义:
语义 | 描述 |
---|---|
SV_POSITION | 裁剪空间中的顶点坐标,必要语义 |
COLOR0、COLOR1 | 通常用于输出第一、二组顶点颜色 |
TEXCOORD0-7 | 通常用语输出纹理坐标 |
- 片元着色器输出时的常用语义
语义 | 描述 |
---|---|
SV_Target | 输出值存储到渲染目标中,等同于DirectX9中的COLOR |
- 调试:Unity中自带UnityShader的调试,在Windows->Analysis->Frame Debugger中(与书中当时的位置稍有不同)。如果想要看到更多的信息,可以在VS等IDE中寻找相关插件。
- 额外补充-代码数学规范: 1、规范化语法 2、避免不必要的计算 3、慎用分支和循环语句(因为开销大) 4、不要除以0