Shader学习.我的游戏画面是怎么被渲染出来的?

#1

以下为个人学习Shader的学习笔记整理,注重于理解与大体原理了解,不会过于深入也肯定会有说的不对的地方还望在包涵的时候帮我指出一下错误之处!感激不尽!

什么是Shader?

Shader 翻译过来就是着色器 其主要扮演的角色是渲染画面流水线时的一员。所以要想了解Shader在这个流水线大工厂里到底干了些什么,我们最好先了解这间渲染工厂到底做了些什么工作,大体的环节以及每个环节的概念,这有助于我们了解这位员工它的主要工作内容。

渲染的大致概述与流程

面包房”(渲染的大体流水线环节)

以下是个人对其大概的概念理解,为了更好的去理解,我愿意将其称为面包房,“面包房”的工作由CPU与GPU一起合作

渲染流水线分为主要三个阶段:

1.应用阶段

2.几何阶段

3.光栅化阶段

专有名词并不能帮助我们去理解这几个概念,但是如果用面包房进行比喻会好很多。

和面团

应用阶段,这个阶段主要由CPU进行负责,其主要需要做的工作其实是开发者进行主导,也就是放置物体,指定摄像机位置,物体的材质球附加,场景中使用的光源等等,在游戏开发的过程中,就是布置关卡环境的环节,其主要过程如上。

由于不在渲染原理范畴内,不过多描述。但它在渲染流程中充当了面包房里的和面阶段,有了面团才能做面包嘛,它最重要的作用是输出渲染信息,也就是渲染图元即面团。设置放好的物体模型与光影设置信息就在这个环节被定了下来,接下来这些环节就会被送往下个阶段。

配用模具,做出面包形状

几何阶段在这个阶段就是处理面团的时候了,集合阶段时,会将渲染图元进行处理,怎样绘制图元,在三维空间里的哪里绘制图元,将其顶点坐标变换到屏幕空间中然后输出其二维顶点坐标并传递给下一个阶段。

屏幕的显示其实只是一个二维的平面,而我们看到的游戏画面其实都是一帧帧绘制出来的,所以这个环节就是将UN中三维的空间信息进行处理成为二维坐标后进行传递,很像做面包或者蛋糕的时候使用模具一样定型,其内部更细致的原理与环节将会之后细述。这一阶段通常在GPU上进行。

烤面包

光栅化阶段由几何阶段传输过来的参数会由GPU进行处理来产生屏幕上的像素,借由这些像素渲染出最终的图像,这个阶段就是烤面包了,为数据的定型进行最终处理,最后输出画面,这一阶段也会在GPU上执行。

以上就是整个渲染流程的大致概念。

CPU与GPU之间的通信

前文提到过,CPU与GPU一起工作,工作之间就有交流,所以它们之间也是有通信的,通信之间,由CPU指导GPU工作,在前面应用阶段准备好了参数与渲染状态之后CPU就要调用一个指令来告诉GPU,嘿!显卡!我的数据都准备好了!你按着我的设置准备开始渲染这一帧画面吧!”这个渲染命令就是Draw Call。通俗点来讲,和面师傅叫面包师做一个菠萝包,材料和做什么和面师傅已经准备和告诉面包师了,接下来就是面包师的工作了。

                                                                                                                                                                                           

额外话题:CPU与GPU之间的通信不止Draw call 这条命令,Draw call应当尽可能的少调用,过多的Draw call 会降低帧率,CPU与GPU之间的工作就好像和面师傅想做100个菠萝包,它对面包师说请帮我制作1个菠萝包。”然后递过去一个和好的面团子,如此重复100次。我们也知道GPU的运算能力十分强大,很多情况下CPU在准备下条命令的时候GPU早就没事干了,而CPU还在准备渲染的数据命令等,这不仅浪费了显卡的计算能力,也花费了过多的时间在Draw call上。

如何减少?方法有很多,这里仅提出批处理的方法。

如果是做菠萝包的话很简单,让和面师傅搓够100个菠萝包的面团子然后告诉面包师:“请制作100个菠萝包,”就好了。

一样的道理,把小的Draw call 合并成一个大的Draw call 就可以了,但请注意,批处理更加适合处理静态物体,比如大楼与地面,因为我们需要在CPU中合并网格,静态物体只用合并一次就好了,动态物体每次运动都需要重新合并网格会产生一定影响。

                                                                                                                                                                                               

以下部分为较为细致的描述几何阶段与光栅化阶段的工作流程

面包师(GPU)的工作

前面提到过,几何阶段光栅化阶段都在GPU上工作,接下来描述的就是这两个阶段其中的一些更细致的一些过程。

接下来是GPU进行这段工作时的流水线

顶点数据 >>>> 顶点着色器 >>>>> 曲面细分着色器 >>>> 几何着色器 >>>> 剪裁 >>>> 屏幕映射 >>>> 三角形设置 >>>>  三角形遍历 >>>> 片元着色器 >>>> 逐片元操作  >>>>> 屏幕图像

绿色部分是几何阶段,蓝色部分则是光栅化阶段

(有一些名词在游戏设置中画质的选项上面看着有点眼熟)

接下来大致描述其中每个部分的功能,其中需要重点描述的是顶点着色器、剪裁、屏幕映射、三角形设置、三角形遍历、片元着色器、逐片元操作。

顶点着色器

顶点着色器,它的处理单位是顶点,每一个输入进来的顶点都会调用一次顶点着色器,他主要的功能有两个:坐标变换,逐顶点光照.

坐标变换就是对顶点的坐标进行某种变换,它在顶点动画中非常有用,布料或者水面的上下波动都需要顶点着色器,它的实现主要是依靠将顶点坐标从模型空间转换到齐次剪裁空间在硬件的透视除法后得到归化一的设备坐标。从我个人的角度来理解就是将传过来的模型顶点坐标数据变换成硬件可以理解的坐标系,进而向下继续传递参数。

剪裁

摄像机不总是盯着一个画面进行输出,当然也会有在视野外的东西,这个时候及时的舍弃这一部分叫做剪裁,在这个环节,完全在视野外的图元将不会向下个环节传递参数,被剪裁的部分会产生新的顶点。

屏幕映射

从其次剪裁空间传输过来的坐标依然还是三维坐标系屏幕映射就是要把三维坐标换成屏幕坐标系与画面分辨率有关,如下图。

其本质是一个缩放的过程。

 注意!不同的接口会产生不一样的坐标系统!

如果的到的图像是倒转的那么可能就是这个原因造成的(坐标系统的差异)

OpenGL与DirectX是不同的图像应用编程接口,简单来讲,其实和面师傅和面包师之间的交流不是简单的说话,显卡知道如何去渲染的时候也需要特定的函数,OpenGL与DirectX则是基本的函数指令。这两家曾因为技术不同而产生竞争,幸而有显卡驱动这个”中介人“的出现,现在基本上所有的GPU都可以与这两种编程接口工作。

三角形设置

这一步开始进入了光栅化阶段,屏幕映射阶段已经输出了屏幕坐标系下的顶点位置以及其他信息,输出的顶点信息其实是都是三角网格的顶点,这个阶段将会借助顶点信息生成三角形网格,为下一个阶段做准备。

 三角形遍历

这个阶段则如图所示,主要是输出片元。

片元着色器

在这个阶段,三角形遍历所产生的数据也就是三角形网格如何覆盖每一个偏远的数值会在这里产生这一系列数据的信息,相当于打包好一块面包的制作方法和材料,接下来的阶段才是真正对像素产生影响的阶段。

这一阶段可以完成许多重要的渲染技术比如纹理采样,在此不过多赘述。

大的要来啦

逐片元操作

接下来这就是渲染流水线最后一步逐片元操作。

这一步主要有两大流程:

1.深度测试模板测试每个片元的可见性。

2.将所有通过测试的片元进行合并或者是混合。

前面所有的阶段都是为了生成一个片元准备的,像是制作面包不仅仅是和面,还有加入其他的配料定型等等,但是一块面包也是要做的好才能拿的出手的,所以要对每个片元进行测试,一个片元只有通过了所有的考试才能获得与GPU谈判的资格即与颜色缓冲区合并,任何一项测试没有通过都意味着这个片元将会被舍弃。

接下来是两种测试的基本原理概述

模板测试

模板测试,GPU在拿到一个片元之后会与比较函数进行一个比对,这个比较函数可以由开发者指定,如果这个片元没有通过这个测试,那么它会被舍弃。不管这个片元有没有通过测试,我们都可以修改模板缓冲区,这样,我们就可以借助这一项测试来控制渲染的区域或者方法,比如渲染阴影或者轮廓。

深度测试

深度测试,顾名思义,它是来测试深度的,这个深度与字面上的意义稍有出入,指的是离摄像机的远近深度,我们总是希望靠近摄像机的显示出来而远处或被遮挡的忽略,这个测试就满足了我们的需求。它不仅可以比较片元是否被遮挡,一个透明的物体的透明效果也与深度测试有关。

合并

当一个片元成功的通过了这两项测试之后,他就可以来到合并步骤了,合并可以选择下一帧的这个片元上的颜色是覆盖掉上一帧的呢还是因为开启了混合模式而与上一个片元叠加?这其中也涉及了半透明物体的处理,不过多细述。

到此为止,一个像素终于被成功的渲染出来了!当然GPU和CPU还要重复千百上亿次这样的工作。

这就是大致的渲染过程原理啦!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值