GPU
显卡的处理器
CPU和GPU的区别
CPU是针对串行的指令设计的,GPU针对大规模的并行计算设计的
CPU的多核并行是针对指令的并行,GPU针对数据与计算的并行
渲染管线
渲染流水线
简单理解:CPU从内存准备数据,传递到GPU,GPU通过一系列的计算最终得到一个二维的图像的过程就是渲染管线
CPU准备数据
顶点坐标(相对于模型本身的物体的坐标系的坐标,模型空间的坐标):模型的顶点
法线信息(模型空间下的)
切线信息(模型空间下的)
纹理坐标(也叫UV坐标)
顶点颜色
主要分为三个阶段
应用程序阶段(CPU)
CPU和内存通信,从内存中取出模型上相关顶点坐标、法线、切线、纹理坐标等,将其组成一个图元发送给GPU
几何阶段(GPU)
变换坐标
将CPU传递来的顶点坐标,转换到裁剪与屏幕空间
四个坐标空间
模型坐标空间(数据顶点坐标、法线、切线都是模型空间下的)
世界坐标空间:绝对的
观察坐标空间:相对于摄像机的,以摄像机为原点
裁剪与屏幕坐标空间
三次转换使用的是矩阵来进行转换的
将变换后的坐标传递到光栅化阶段
转换坐标的作用:
CPU取出的顶点数据都是相对于模型本身的,也就是相对于模块空间的
将顶点坐标从object space转换到world Space判断当前的顶点在世界中哪个位置
将world space的顶点位置转换到eye space判断顶点相对于摄像机的位置
将eye space的顶点坐标转换到clip and project space 裁剪到摄像机视锥体外部顶点,并且将视锥体内的顶点投影降维映射到屏幕坐标上
顶点函数在几何阶段
光栅化阶段(GPU)
使用上一个阶段的数据,计算屏幕像素的颜色,渲染出二维的图像
片元函数在光栅化阶段
Shader
着色器,用来实现图像渲染的可编辑程序
在Unity中Shader通过Material作用到物体上的
着色器语言
HLSL
针对于Direct3D
High Level Shader Language
GLSL
针对于OpenGL
OpenGL Shading Language
Cg
同时支持Direct3D与OpenGL
NVIDIA公司出的
C for Graphics
图像编程接口
Direct3D
微软出的
OpenGL
多个公司组成的OpenGL架构评审委员会制定的
Unity着色器分类
固定函数着色器
最简单的着色器
使用Unity提供固有的函数来完成渲染
Shader Lab命令来完成
顶点/片元着色器
效果最丰富的,但是复杂度最高的着色器
Unity中使用Cg语言或HLSL语言完成
组成
顶点函数
片元函数
表面着色器
Unity独有的
对Cg进行了一层封装,比顶点/片元简单,但是灵活度没有顶点/片元高
Shader的基本结构
Shader名字
Shader名字,支持层级结构
Properties 属性
属性类型
Color:颜色
float:常数
Vector:四维向量
Range:范围,最大值与最小值,还是一个数,只是规定的了最大值与最小值
2D:普通纹理贴图
Cube:立方体贴图, 应用在天空盒的
SubShader
包含渲染的计算过程
可以有多个SubShader
Pass
在SubShader中的结构,可以有多个
多个Pass情况下,所有的Pass都会执行,每执行一个Pass增加一个DrawCall
顶点片元着色器或固定函数着色器写在Pass结构中
FallBack(备用shader)
指定备用Shader,当所有的SubShader失效时,执行FallBack指定的Shader
固定函数着色器
Lighting
Lighting off : 关闭灯光影响
Lighting on : 开启灯光影响
Color
显示颜色
Color(r,g,b,a)
Color[属性名]
Material
灯光影响的命令需要放在Material中
Diffuse
漫反射命令
Diffuse[颜色属性] : 漫反射的颜色
颜色的数学运算
颜色的加法使颜色变亮
(r1,g1,b1,a1) + (r2,g2,b2,a2) = (r1 + r2, g1 + g2, b1 + b2, a1 + a2)
颜色的乘法使颜色变暗(颜色叠加指的是颜色相乘)
(r1,g1,b1,a1) * (r2,g2,b2,a2) = (r1 * r2, g1 * g2, b1 * b2, a1 * a2)
渲染队列(Render Queue)
渲染队列在Shader中实际是一个数值
渲染队列值决定对象物体的渲染顺序,渲染队列值越小的越先渲染,渲染队列值越大的越后渲染
渲染队列只决定渲染的先后顺序,最终在屏幕上的显示不是完全由渲染队列决定,还与深度比较与深度写入相关
语法
Tags{"Queue"="渲染队列名称"}
渲染队列名称
Background
天空盒:1000
Geometry
不透明的物体:2000
AlphaTest
有透明通道,使用AlphaTest命令:2450
Transparent
半透明物体,使用Blend命令进行混合:3000
Overlay
镜头特效:4000
裁剪命令(Cull)
关闭裁剪
Cull Off:正面与反面都显示
裁剪正面
Cull Front:只显示反面,不显示正面
裁剪反面
Cull Back:只显示正面,不显示反面
正面与反面
法线的方向就是正面
反之就是反面
深度测试与深度写入
深度
简单理解为游戏物体距离摄像机的距离
深度越大证明距离摄像机越远,天空盒深度可以认为无限大的
深度缓冲区
在图形设备的内存中,存在一块存储区存储的是每个像素的深度值。通过深度缓冲区进行深度测试,从而确定遮挡关系,保证渲染正确
颜色缓冲区
图形设备的内存中,存在一块存储区存储的是每个像素的颜色。最终像素显示的颜色就是颜色缓冲区的颜色
深度测试
当前游戏物体的深度与深度缓冲区的深度的比较过程叫做深度测试
命令
ZTest Less:小于比较
ZTest Greater:大于比较
ZTest LEqual:小于等于比较
ZTest GEqual:大于等于比较
ZTest Equal:是否等于
ZTest NotEqual:不等于
ZTest Always:将比较关闭,直接认为比较成功
深度写入
将当前物体的深度写入到深度缓冲区的过程就是深度写入
命令
ZWrite On:开启深度写入
ZWrite Off:关闭深度写入
总结
深度测试成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区
深度测试成功,深度写入关闭,颜色写入缓冲区,深度不写入缓冲区
深度测试失败,深度写入开启,颜色不写入缓冲区,深度不写入缓冲区
深度测试失败,深度写入关闭,颜色不写入缓冲区,深度不写入缓冲区
深度测试关闭,深度写入开启,颜色写入缓冲区,深度写入缓冲区
实例1:渲染遮挡关系判断机制
深度:天空盒(∞),YellowCube(a), GreenCube(b)
中心像素点的判断: 天空盒, Yellow Cube,Green Cube
渲染队列: 天空盒(1000), YellowCube(2000), GreenCube(2000)
深度测试:天空盒(<),YellowCube(<),GreenCube(<)
深度写入:都是开启
开始比较过程
颜色缓中区 |
深度缓中区 |
|
|
第一比较:深度测试渲染队列最小的,天空盒的深度与深刻缓冲区的深度进行小于比较
此时深度缓冲区无深度,认为比较成功,将天空盒的颜色写入到颜色缓冲区中,将天空盒的深度写入到深度缓冲区中。
颜色缓中区 |
深度缓中区 |
天空盒颜色 |
∞ |
第二比较:深度测试渲染队列比天空盒大的(Yellow 与 Green随机一个),Green的深度(b)与深度缓冲区的深度(∞)进行小于比较
b < ∞ 比较成功, 将Green的颜色写入颜色缓冲区,将Green的深度写入深度缓冲区。
颜色缓中区 |
深度缓中区 |
绿色 |
b |
第三比较:深度测试Yellow(a)与深度缓冲区的深度(b)进行小于比较
a < b 比较成功,将Yellow的颜色写入到颜色缓冲区,将Yellow的深度写入到深度写入到深度缓冲区。
颜色缓中区 |
深度缓中区 |
黄色 |
a |
判断到已经没有其他物体,深度测试全部完成,最终中心像素点显示的颜色就是颜色缓冲区的颜色,黄色
第2种方式开始比较过程
颜色缓中区 |
深度缓中区 |
|
|
第一比较:深度测试渲染队列最小的,天空盒的深度与深刻缓冲区的深度进行小于比较
此时深度缓冲区无深度,认为比较成功,将天空盒的颜色写入到颜色缓冲区中,将天空盒的深度写入到深度缓冲区中。
颜色缓中区 |
深度缓中区 |
天空盒颜色 |
∞ |
第二比较:深度测试渲染队列比天空盒大的(Yellow 与 Green随机一个),Yellow的深度(a)与深度缓冲区的深度(∞)进行小于比较
a < ∞ 比较成功, 将Yellow的颜色写入颜色缓冲区,将Yellow的深度写入深度缓冲区。
颜色缓中区 |
深度缓中区 |
黄色 |
a |
第三比较:深度测试Green(b)与深度缓冲区的深度(a)进行小于比较
a < b 比较失败,颜色不写颜色缓冲区,深度不写入深度缓冲区
颜色缓中区 |
深度缓中区 |
黄色 |
a |
判断到已经没有其他物体,深度测试全部完成,最终中心像素点显示的颜色就是颜色缓冲区的颜色,黄色
实例2:复杂渲染遮挡关系
渲染队列:天空盒(1000),Green(2500),Blue(3000),Red(3500)
深度:天空盒(∞),Green(G),Blue(B),Red(R)
深度测试:天空盒(小于),Green(小于),Blue(大于),Red(大于)
深度写入:天空盒(开启),Green(开启),Blue(关闭),Red(开启)
开始比较过程
比较顺序:天空盒 –> Green -> Blue -> Red
颜色缓冲区 |
深度缓冲区 |
|
|
第一次比较:天空盒的深度(∞)与深度缓冲区的深度(无)进行比较
比较成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区
颜色缓冲区 |
深度缓冲区 |
天空盒颜色 |
∞ |
第二次比较:Green的深度(G)与深度缓冲区的深度(∞)进行小于比较
G < ∞:比较成功,深度写入开启,颜色写入缓冲区,深度写入缓冲区
颜色缓冲区 |
深度缓冲区 |
绿色 |
G |
第三次比较:Blue的深度(B)与深度缓冲区的深度(G)进行大于比较
B > G:比较成功,深度写入关闭,颜色写入缓冲区,深度不写入缓冲区
颜色缓冲区 |
深度缓冲区 |
蓝色 |
G |
第四次比较:Rad的深度(R)与深度缓冲区的深度(G)进行大于比较
R > G:比较失败,颜色不写入,深度不写入
颜色缓冲区 |
深度缓冲区 |
蓝色 |
G |