管线渲染
定义:图形数据在GPU上经过运算处理,最后输出到屏幕的过程
1. 顶点处理: 接收模型顶点数据、坐标系装换
2. 图元装配: 组装面、连接相邻的顶点,绘制为三角面
3. 光栅化 : 计算三角面上的像素,并为后面着色阶段提供合理的插值参数(以及深度值)
4. 像素处理: 对每个像素区域进行着色、写入到缓存
5. 缓存: 一个存储像素数据的内存块,最重要的缓存是帧缓存与深度缓存
帧缓存:存储每个像素的色彩(缓冲)
深度缓存Z-buffer:前后排序(深度信息,物体到摄像机的距离)
6. Draw Call 绘制调用:每帧调用显卡渲染物体的次数
什么是缓冲?
一个像素有如下缓冲
颜色缓冲Color buffer/prixel buffer: 储存该点即将显示的颜色,RGBA值
深度缓存 depth buffer/Z buffer: 储存该点的深度Z
模板缓存stencil buffer : 通常作用限制渲染区域。更高级用法需结合深度缓存,例如某像素的模板缓冲值会随着其是否通过深度缓冲测试而改变
什么是图元装配(Primitive Assembly)
经过变换的顶点 被装配成几何(三角形等)图集
什么是光栅化(栅格化)(Rasterization)
栅格化这个术语:可以用于任何将矢量图形转化成栅格图像的过程
在3D渲染中主要是指,三角形等图元(矢量)转化成像素碎片的过程。或者说决定哪些像素几何图元覆盖的过程。栅格化的结果是像素位置的集合和片段的集合
什么是光栅操作(Raster Operation)
指在碎片fragment处理后,在更新帧缓存前最后执行的一系列操作。通过包括裁剪,深度测试,alpha测试,alpha混合等。
Shader常见术语
Alpha 透明的(黑透白不透、灰色半透半不透)
Bump凹凸 (法线贴图)
Specular (高光)
Shader主要看Game视窗
Shader显示名称与Shader名不冲突
什么是GPU?
GPU:Graphic Processing Unit,中文翻译为“图形处理器”。显卡包括(GPU,显存,显卡BLOS,显卡PCB板)
什么是Shader?
Shader程序:GPU执行的,针对3D对象进行操作的程序
Shader编程有那几种?
CG:与DirectX 9.0 以上以及OpenGL 完全兼容。运行时或事先编译成GPU汇编代码
HLSL: 主要用于Direct3D。平台:Windows
GLSL: 主要用于OPenGL。 平台:移动平台(IOS,Android),Mac(only use when you target Mac OS X or OpenGL ES 2.0)
为什么Shader中选择CG?
因为CG/HLSL 比GLSL支持更多的平台。
Unity3d 里CG输出什么?
Windows平台:Direct3D,GPU汇编代码
Mac: OpenGL GPU汇编代码
Flash: Flash GPU 汇编代码
IOS/Android : unity 会将CG转换成GLSL代码。
总结:也就是除了移动平台会把CG转换成GLSL代码,其余平台都是转化成汇编代码。
Unity 中的三种自定义Shade:
1.surface shaders, 表面着色器(最常用,比固定功能管线高级)(之前默认创建的shader类型)它是 Vertex and fragment shaders 的包装,让我们可以不用关心这些顶点和片段程序的细节,可以直接得到我们想要的着色器。
2.Vertex and fragment shaders 顶点和片元着色器(细节处理,偏底层)
3.fixed function shaders. 固定功能管线着色器(更简单),在可编程渲染管线硬件出现之前,很多光照都会放在硬件级处理(可以理解为对固定管线硬件的操作),一般放在项目前绝大多数硬件都可支持,应用就可以使用,比如光照、纹理采样
//Shader中没有注明是前两种shader,即为第三种shader
先从ShaderLab基本语法开始入手,再去阅读surface shader,或者vertex and fragment shaders
ShaderLab 基本结构
Unity中的Shader 都是要通过ShaderLab的基本语法进行编写,unity就是想通过Shaderlab的方案进行Shader的编写。将三种定义的Shader通过同一种格式进行编写,避免不同Shader使用不同的方法。
Shader "name"
{
//[Properties] 属性 查看ShaderLab:Properties
//作用:在可视化面板提供美工可使用的属性
Properties
{
}
//[Subshader] 算法用于执行给定的数据
SubShader
{
}
//[FallBack] 后退 一般会填写所有硬件都支持的渲染方式
FallBack "Diffuse"
}
关于SubShaders (处理ShaderLab中的语言片段) 在ShaderLab中至少有一个SubShader,当然也可多个。但是,显卡每次渲染处理的时候只能选择一个SubShaders执行。那多个SubShader的作用是为了不同的硬件的渲染支持,为了Shader能在比较老的图形显卡中也能支持。一般比较往下的Subshader要简化,运算指令要简单。
Fixed function shader固定功能管线
所有硬件平台都可支持,针对硬件能够执行的基本命令的Shader,当然有,但是,速度最快
Properties 属性
Material 材质
Lighting 光照
Settexture 设置纹理
Pass通道(存储图像的色彩RGB)(只有Surface 可以不写)
Surface shaders
surfaceOutPut输出
Input 输入
Lighting 光照
常用公式
环境反射
Ambient= Ka*globalAmbient;
Ka是材质的环境反射系数
globalAmbient是入射环境光的颜色
漫反射
Diffuse=Kd*lightColor*max(N*L,0);
Kd 是材质的漫反射颜色
lightColor是入射漫反射光的颜色
N 是规范化的表面法向量
L 是规范化的纸箱光源对的向量;
镜面反射
Specular=Ks * lightColor *facing*max((N*H),0) shininess
Ks 是材质的镜面反射颜色;
lightColor是入射镜面反射光的颜色
N是规范化的表面法向量
V是指向视点的规范化的向量
L是指向光源的规范化的向量
H是V和L的中间向量的规范化向量
P是要被着色的点
Faceing是1如果N*L是大于0的,否者为0
写Shader不区分大小写
和灯光有呼应的 ------ 漫反射 高光 背光 阴影 环境光
固定着色器格式
hader "Unlit/Test2"//不区分大小写
{
//声明属性
Properties
{
//默认颜色颜色
//变量名 在监视面板显示的名称 类型=值
_Color("MyColor",Color)=(1,0,0,1)
//环境光
_Ambient("Ambient",Color)=(1,0,0,1)
//高光
_Specular("Specular",Color)=(1,0,0,1)
_Shininess("Shininess",Range(0,1))=0.5 //range 0-8的值
//自发光
_Emission("Emission",Color)=(1,0,0,1)
//
_MainTexture("Main Texture",2D)="white"{}
//默认颜色
}
SubShader
{
pass
{
Color[_Color] //使用默认颜色进行颜色的写入
Material{
//漫反射
Diffuse[_Color]
//环境光
Ambient[_Ambient]
//亮度
Shininess[_Shininess]
//高光反射系数
Specular[_Specular]
//自发光
Emission[_Emission]
}
//启动光照
Lighting On
//启动高光反射
SeparateSpecular On
SetTexture[_MainTexture]
{
Combine Texture*primary double
}
}
}
FallBack "Diffuse"
}
表面着色器格式
Shader "Custom/Test1" {
//属性
//属性变量
Properties {
//变量名 面板中的名字 类型
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
//算法
SubShader {
Tags { "RenderType"="Opaque" } //描述渲染类型,当前是不透明的物体
//Tags{"RenderType"="Opaque" "queue"="transparent"}//透明的物体
LOD 200 //层级细节
CGPROGRAM //CG代码块 CG开始
// Physically based Standard lighting model, and enable shadows on all light types
//如果是Standard fullforwardshadows光照模型,则对应用SurfaceOutputStandard,
//如果是Lambert光照模型(其他版本Unity默认的光照模型),则对应SurfaceOutput。
//对应的SurfaceOutputStandard/SurfaceOutput结构体不用写出来
#pragma surface surf Standard fullforwardshadows//编译指令
//surface表面着色器 surf调用的方法 Standard基于物理的光照模型(原来是漫反射 Lambert)
//fullforwardshadows 阴影表现(平行光、点光、聚光都是有阴影的)
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0 //GPU硬件支持3.0 (不写默认是2.0)
sampler2D _MainTex; //CG中图片的类型
struct Input {
float2 uv_MainTex; //记录uv纹理坐标
};
half _Glossiness; //CG中的浮点型
half _Metallic;
fixed4 _Color; //CG中的四阶向量(0,0,0,0)rgb
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_CBUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_CBUFFER_END
//Input 传入值 inout 传出值(基于物理的要加Standard)
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic; //金属光泽表现
o.Smoothness = _Glossiness; //高光光泽度
o.Alpha = c.a;
}
ENDCG //CG结束
}
FallBack "Diffuse"
}
表面着色器示例练习
Shader "Custom/Test5" {
Properties {
//2D ---图片 white----默认格式 “”内也可以不写
//大括号也可以不写(大括号内可以给值)
_MainTex("Texture",2D)="white"{}
_BumpMap("Bumpmap",2D)="bump"{}
//cube 立方体贴图
_Cube("Cubemap",CUBE)=""{}
}
SubShader {
//不透明
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
//如果是Standard fullforwardshadows光照模型,则对应用SurfaceOutputStandard,
//如果是Lambert光照模型(其他版本Unity默认的光照模型),则对应SurfaceOutput。
//对应的SurfaceOutputStandard/SurfaceOutput结构体不用写出来
#pragma surface surf Lambert
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
struct Input {
//只要是纹理相关都需要UV
float2 uv_MainTex;
float2 uv_BumpMap;
float3 worldRef1;
INTERNAL_DATA //反射与法线效果配合
};
//再次声明变量
sampler2D _MainTex;
sampler2D _BumpMap;
samplerCUBE _Cube;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_CBUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_CBUFFER_END
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo=tex2D(_MainTex,IN.uv_MainTex).rgb;
//不需要法线的反射效果
//o.Emission=texCUBE(_Cube,IN.worldRefl).rgb;
//法线与反射效果配合
//需要将INTERNAL_DATA添加到Input结构中
o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));
//反射
o.Emission=texCUBE(_Cube,WorldReflectionVector(IN,o.Normal)).rgb;
}
ENDCG
}
FallBack "Diffuse"
}
介绍: 【Unity5.x Shaders】最基本的Surface Shader-Diffuse shader以及Surface中的三种输出结构