渲染管线

渲染管线的重要性

  1. 从事游戏开发行业,了解shader编程至关重要,而要想掌握shader编程,就必须理解渲染管线。而学习渲染管线后,我们就能明白一个模型是如何将它渲染到屏幕上的。
  2. shader,其名为着色器,根据其名字,我们大概能明白它的作用:即给模型上色,当然,它的作用不仅仅如此,更重要的是我们可以利用着色器实现自己想要的屏幕效果,比如屏幕特效,模型顶点运动(如草的飘动),消融等效果。而想要实现这些效果,我们就要学会shader编程。
  3. 游戏引擎涉及非常多关于渲染的知识,对于游戏开发者来说,我们不应该只会用游戏引擎做游戏,还要理解游戏引擎的工作原理,这样才能针对项目做到对应的优化。

Unity渲染管线简介

学习shader编程,首先就要熟记渲染管线,注意我是说熟记,这是我在网上找的一张示意图:
渲染管线_第1张图片

看到这个图我们大概能明白为什么它叫渲染管线了:因为它的工作流程就像工厂的流水线一样,按照一定的顺序在执行,这也是渲染管线里的核心步骤:

  • 顶点着色器(Vertex Shader)

数据从CPU向GPU进行传递,首先,
数据从模型中获得,包括顶点坐标,法线,切线,颜色信息
接着,这些数据会进入顶点着色器(Vertex Shader),最关键的操作是对顶点坐标进行变换,如将顶点坐标从物体空间变换到相机空间,(使用矩阵乘法,因此不会矩阵的初学者还要有线性代数的基础知识)为什么要做空间变换呢,因为我们要确定这个顶点是否在相机的世界下可见,如果不可见还要将它剔除掉,这里判断可见性同样需要使用矩阵变换,变换之后判断它的值(x,y,z)的范围是否在(-1.1)之间,如果在就说明相机可见,如果不在就要剔除掉。同时,我们可以在这个shader中做定点动画,如草的飘动,旗子的飘动等,这便需要我们来写shader代码。

  • 图元装配
    图元装配(Primitive Assembly)阶段将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),并所有的点装配成指定图元的形状;
    图元装配阶段的输出会传递给几何着色器(Geometry Shader)。几何着色器把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状。例子中,它生成了另一个三角形。
  • 光栅化
    变换过坐标的顶点接下来进入片元着色器,不过在通过片元着色器运算之前,有一个光栅化的过程,我们想一下,点是不连续的,但是在屏幕上的像素是连续的,像素的数量远远多于顶点数,这要怎么做映射呢,即顶点应该对应哪一个像素,解决的方式就是插值。
    插值是什么
    target=t*a+(1-t)*b;
    这是一元插值的核心,当然还有二元插值,多元插值,当t为1时它的值为a,当t为0时他的值为b,如果a和b是两个顶点,那么两个顶点之间的缺少的“顶点”就能通过插值计算出来了,这样就能将屏幕空间各个坐标对应的点的信息都能计算出来,这就是光栅化(将顶点坐标转换为像素坐标)
  • 片元着色器(Fragment Shader)

计算完成的像素坐标又是新的坐标信息了,我们又可以利用这些信息做一些计算,比如说光照处理,在顶点着色器的光照和在片元着色器的光照计算完全不是一个数量级,因此最重要的光照(在unity中,一般是直射光)会使用片元着色器进行计算,其他乱七八糟不重要的光照会在顶点着色器中进行计算,或者使用球谐函数。

那么,有光自然就得有阴影,如果场景里存在大量光照,这对渲染性能的影响非常巨大,因此,相对于光照前向渲染,又出现了延迟渲染,这样能使时间复杂度从O(m*n)将为O(m+n),而最后的像素信息需要保存在G-Buffer中,因此延迟渲染有点类似于空间换时间,这里不做详细说明。

最后就是将最终的信息存入帧缓存中,这也是屏幕上将要显示的最终像素。

  • 学习经验分享
    在学习shader时,一定要从根源学习,多问“为什么”,以及了解其发展过程,为什么会出现相关的技术,比如early-z,这样我们就能更快理解其原理,也能更快上手编程及实战,实现我们想要的效果。

你可能感兴趣的:(游戏,Shader)