渲染原理

这是我在《游戏架构-核心技术与面试精粹》看的,记录一下~

啥玩意是渲染?
游戏图像的绘制被称为渲染

啥玩意是渲染管线?
表示绘制到游戏视图的过程中,一个模型文件的数据经过了哪些转换步骤
通常指的是GPU流水线,不包含CPU部分

CPU主要是准备好顶点、贴图、法线、灯光方向、颜色等东西之后,告诉GPU
GPU接收到数据后,就要对其处理最终显示到屏幕上

因为屏幕是2D画面,模型是3D资源,必然有一部操作,就是将3D转化为2D。
这个操作之前被称为顶点阶段(几何阶段),主要是处理3D模型数据
之后被称为片元阶段(光栅化阶段),处理2D像素数据

1.顶点着色器(Vertex Shader)
如下所示:

#pragma vertex vert
struct v2f
{
  float4 pos : SV_POSITION;
  fixed4 color : COLOR;
};
v2f vert (appdata_base v)
{
  //vertex operation
}

每个顶点都会调用一次这个函数,并转化为这个函数的输出,这些输出被称为图元(Primitive)
一般可以在这里改变顶点或者法线相关信息

2.曲面细分(Tessellation Shader)
是OpenGL 4.0新加入的特性,很多设备还不支持
主要的作用是可以优化曲面,eg:使曲面更平滑

3.几何着色器(Gemoetry Shader)
几何着色器的输入输出都是图元(Primitive),不是顶点
可以将简单的图元扩展成更为复杂的形式

4.变化回执(Transform Feedback)
是在OpenGL 3.0之后加入的特性
可以将图元存放到 Transform Feedback Buffer中,并可以决定是否按照先前的流程光栅化
主要特性:在下一帧渲染时,可以得到上一帧图元的数据,对于定量变化的情况,可以节省掉流水线之前的步骤
(常被用于粒子系统 or 角色的头发)

5.裁剪(Clipping)
图元会根据视域的平截头体(Frustums)做可见性判断
区域外的定点会被舍弃,与这个定点连线的三角形的边会与平截体求交点,这些交点就变成裁剪后的新顶点

6.屏幕映射(Screen Transform)
图元的坐标从齐次裁剪空间变换到屏幕空间

7.图元装配(Primitive Assembly)
顶点会被转化成基础图元,供后续步骤使用
三角形的朝向剔除(Face Culling)是在这个阶段完成的

8.光栅化(Rasterization)
三角形会经历两个步骤:
1.三角形会被转化成片段
2.会遍历三角形,获取顶点属性进行插值,在每个像素点上产生一个插值

如果开启了多重采样抗锯齿(Multisample Antialiasing,MSAA),此处就会对每个像素进行多次采样,产生多个偏远,最后在混合,以达到抗锯齿的效果

9.提前深度测试(Early Depth Test)
检查片元的深度,如果不需要显示则丢弃它
可以在片元着色器运行之前去掉不合理的值,减少运算的消耗
但是与后续的透明测试有冲突,如果在后续的透明度测试中失败,这步深度测试也不应该将其通过
有些GPU会判断是否有此类冲突,如果有就跳过(有一定消耗)

10.片元着色器(Fragment Shader)
可以自定义光照计算、读取贴图颜色、设置透明度等
输入是光栅化后得到的片元数据,输出值也为片元数据
Unity中会把函数返回值写为运算后的颜色

fixed4 frag (v2f i) : SV_TARGET
{
  //do framgent operation
}

11.逐片元操作(Pre-Sample Operation)
这个阶段:主要是先测试后混合

测试共经历了4个测试:
他们的作用都是确定一个像素是否应该显示

1.裁切测试(Scissor Test)
通过区域判断的,与基于顶点的 Clipping 阶段不同

2.透明测试(Alpha Test)
透明度达不到,就不绘制

AlphaTest Greater 0.5

3.模板测试(Stencil Test)
通过缓冲区来进行像素比较,与ColorBuffer或DepthBUffer,StencilBuffer是一个8位图像,每个像素保存一个无符号整型

Stencil
{
  Ref 2
  Comp equal
  Pass Keep
  ZFail decrWrap
}

//也就是,通过按位与的操作比较两侧结果

if((RefValue & readMask) comparisonFunction (StencilBUfferValue * readMask))
{
  pass;
}
else
{
  discard;
}

4.深度测试(Depth Test)
通过深度缓冲区的比较,判断是否应该绘制像素
需要先制定深度写入规则,然后再指定比较规则
分别对应Unity的 ZWrtie 和 ZTest
(深度写入不透明物体默认打开,透明物体默认关闭,测试方法默认是小于等于)

混合阶段主要有2个阶段:
1.混合(Blending)
通过测试的颜色与ColorBuffer中颜色的叠加方式
混合有多种叠加方式,一般会使用RGBA的值作为计算因子,采用插值的方式进行线性计算

Blend SrcAlpha OneMinusSrcAlpha

2.写入遮罩(Write Mask)
主要是颜色遮罩(Color Mask),在最终绘制时,对颜色进行过滤

ColorMask RG

so,
经过上面所有的步骤后,最终这个像素会被绘制到颜色缓冲区,并被显示到屏幕上

你可能感兴趣的:(渲染原理)