所有步骤并行
由一个三维场景触发、生成(渲染)一张二维图像
应用阶段 --(输出渲染图元)->几何阶段–(输出屏幕空间的顶点信息)->光栅化阶段
CPU -> GPU -> GPU
硬盘(HDD) – CPU – 系统内存(RAM) – GPU – 显存(VRAM)
设置使用哪个顶点着色器 片元着色器 光源属性 材质来去渲染
DrawCall是由CPU发给GPU的一个命令
CPU通过DrawCall来告诉GPU开始进行一个渲染过程,一个DrawCall会指向本次调用需要渲染的图元列表
对于几何阶段和光栅化阶段 开发者无法拥有绝对的控制权 但是GPU向开发者开放了很多的控制权
几何阶段:
1、顶点着色器 (可编程的 必实现) 实现顶点的空间变换,顶点着色等功能
2、曲面细分着色器 (可选) 细分图元
3、几何着色器 (可选) 执行逐图元的着色操作,或者被用于生产更多的图元
4、裁剪 (可配置 不可编程) 将不在视野内的图元裁剪掉,剔除某些图元的面片
5、屏幕映射 (不可配置 不可编程) 把每个图元的坐标转换到屏幕坐标系中
光栅化概念阶段:
1、三角形设置 (不可配置 不可编程) 固定函数阶段
2、三角形遍历 (不可配置 不可编程) 固定函数阶段
3、片元着色器 (可编程) 实现逐片元的着色操作
4、逐片元操作 (不可编程 可配置) 修改颜色、深度缓冲、进行混合
输入来自于CPU 处理单位是顶点 -->输入进来的每个顶点都会调用一次顶点着色器
主要工作:坐标变换(把顶点坐标从模型空间转换到齐次裁剪空间)和逐顶点光照
不在视野范围的物体不需要被处理。
图元和摄像机的关系:
1、完全在视野内:传递给下一流水线阶段
2、完全在视野外:不向下传递
3、部分在视野内:裁剪 在这个图元与视野边界处建立新的顶点代替(新的顶点生成 外部顶点舍弃)
输入为三维坐标系下的坐标
任务是把每个图元的x和y转换到屏幕坐标系 是一个缩放的过程
屏幕映射不会对输入的z进行处理 屏幕坐标和z坐标一起构成了窗口坐标系
OpenGL 左下角为0,0
DirectX 左上角为0,0
计算每个图元覆盖了那些像素 为这些像素计算他们的颜色
根据上一阶段来判断三角网格覆盖了哪些像素,并使用三个顶点信息对整个覆盖区域的像素进行插值,如果被覆盖则生成一个片元,最后输出一个片元序列
(一个片元不是真正意义上的像素,而是包含了很多状态的几何,用于计算每个像素的最终颜色)
根据数据插值输出一个或者多个颜色值
决定可见性:
通过模板测试和深度测试来确定是否舍弃片元
混合:
对于半透明物体 需要混合来让物体看是透明的
双重缓冲:后置缓冲 前置缓冲
一旦场景被渲染到了后置缓冲中 GPU就会交换后置缓冲和前置缓冲(之前显示在屏幕上的图像) 保证我们看到的图像信息总是连续的
由于开发者想访问GPU是一件非常麻烦的事情,OpenGL/DirectX作为图像应用编程接口,在这些硬件的基础上实现了一层抽象,可用来渲染二维或者三维图形。可以说这些借口架起了上层应用程序和底层GPU的沟通桥梁。
这些都是高级着色器语言
DirectX的HLSL(High Level Shading Language)
OpenGL的GLSL(OpenGL Shading Language)
NVIDIA的CG(C for Graphic)
这些语言会被编译成中间语言,再交给显卡驱动翻译成GPU可以理解的机器语言
CPU调用图像编程接口 如OpenGL的glDrawElements命令或者DirectX中的DrawIndexedPrimitive命令,以命令GPU进行渲染操作
CPU和GPU并行操作试用命令缓冲区。CPU添加命令 GPU执行
CPU需要完成很多前置工作才能提交一个Draw Call命令 但是GPU渲染能力很强,可以做的很快。如果CPU把大量时间用在提交Draw Call上 则会造成CPU的过载。
批处理思想:把很多小的DrawCall合并成一个大的DrawCall
在游戏开发中,为了减少Draw Call的开销 有两点需要注意
1、避免使用大量小网格,当不可避免时考虑是否可以合并
2、避免使用过多的材质,尽量在不同网格之间共用一个材质
没有对流水线阶段的完全控制权,只是给开发者提供一些配置操作
Shader就是:
1、GPU流水线上一些可高端变成的阶段
2、有一些特定类型的着色器(顶点着色器、片元着色器)
3、控制流水线中的渲染细节