面试知识总结——图形学/OpenGL/3D数学/Unity

1. 场景管理的数据结构:

面试知识总结——图形学/OpenGL/3D数学/Unity_第1张图片

总结,游戏开发最常用的空间数据结构是四叉/八叉树和BVH树,而BSP树基本上只能应用于编辑器上,k-d树则只能用在特殊问题应用场景。

2. 帧同步与状态同步:

https://gameinstitute.qq.com/community/detail/132935
https://gameinstitute.qq.com/community/detail/115782

3. 描述一下渲染管线?

渲染管线的主要功能是决定在给定虚拟相机、三维物体、光源、照明模式,以及纹理等诸多条件的情况下,生成或绘制一幅二维图像的过程。概念上可以将图形渲染管线分为三个阶段:应用程序阶段、几何阶段、光栅化阶段。

面试知识总结——图形学/OpenGL/3D数学/Unity_第2张图片

参考《RTR3提炼总结》P6-P32,《Unity Shader入门精要》P6-P17。

4. 齐次坐标: 既能够用来明确区分向量和点,同时也更易用于进行仿射变换。

https://guangchun.wordpress.com/2011/10/12/affineandhomogeneous/
https://www.cnblogs.com/csyisong/archive/2008/12/09/1351372.html
https://zhuanlan.zhihu.com/p/73123357

5. 屏幕后处理?

将场景渲染到一个附加到帧缓冲对象上的颜色纹理中,之后将在一个横跨整个屏幕的四边形上绘制这个纹理。既然整个场景都被渲染到了一个纹理上,我们可以简单地通过修改纹理数据创建出一些非常有意思的效果。
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/05%20Framebuffers/

6. 延迟渲染?

可以将延迟渲染( Deferred Rendering)理解为先将所有物体都先绘制到屏幕空间的缓冲(即 Gbuffer, Geometric Buffer,几何缓冲区)中,再逐光源对该缓冲进行着色的过程,从而避免了因计算被深度测试丢弃的⽚元的着色而产⽣的不必要的开销。 也就是说延迟渲染基本思想是,先执行深度测试,再进行着色计算,将本来在物空间(三维空间)进行光照计算放到了像空间(二维空间)进行处理。
延迟渲染的优点:

  • 只渲染可见的像素,节省计算量。
  • 对后处理支持良好。
  • 在大量光源的场景优势尤其明显。

延迟渲染的缺点:

  • 内存开销较大。
  • 读写 G-buffer 的内存带宽用量是性能瓶颈。
  • 对半透明物体的渲染存在问题。在这点上需要结合正向渲染进行渲染。
  • 对多重采样抗锯齿(MultiSampling Anti-Aliasing, MSAA)的支持不友好,主要是因为内存开销和内存带宽需要太大。
  • 由于对像素点进行着色,无法针对每种物体使用自定义的着色器。

Gbuffer中保存的信息包括:顶点位置向量、漫反射颜色向量、法向量、镜面强度(Specular Intensity)浮点值、光源的位置和颜色向量、摄像机的位置向量等等。

另外可参考:
https://learnopengl-cn.github.io/05%20Advanced%20Lighting/08%20Deferred%20Shading/
https://zhuanlan.zhihu.com/p/102134614

7. 着色处理方法?

平滑着色(Flat shading)、高洛德着色(Gouraud shading)、冯氏着色(Phong shading)。
高洛德着色的缺点:

  • 着色后仍然可以看出一个个小平面的效果
  • 高洛德着色对于强高光反射的表面, 可能会产生失真(artifacts)。如果在多边形的中心有高光,而且这个高光没有扩散到该多边形的任何顶点,使用Gouraud着色法就不会渲染出任何效果;而如果正好是多边形的顶点上有高光,那么这个点上的高光是正确的,但插值会导致高光以很不自然的形式扩散到相邻的多边形上。
  • 另外注意 Phong Shading 和 Phong Lighting Model 的区别,前者是考虑如何在三个顶点中填充颜色,而后者表示的是物体被光照产生的效果。

参考《RTR3提炼总结》P38

8. 透明物体渲染?

要想让混合在多个物体上工作,我们需要最先绘制最远的物体,最后绘制最近的物体。普通不需要混合的物体仍然可以使用深度缓冲正常绘制,所以它们不需要排序。但我们仍要保证它们在绘制(排序的)透明物体之前已经绘制完毕了。当绘制一个有不透明和透明物体的场景的时候,大体的原则如下:

  • 先绘制所有不透明的物体。
  • 对所有透明的物体排序。
  • 按顺序绘制所有透明的物体。

https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/

9. Draw Call?

DrawCall很简单,就是CPU对图形绘制接口的调用,CPU通过调用图形库(directx/opengl)接口,命令GPU进行渲染操作。每一次绘制CPU都要调用DrawCall,而在调动DrawCall前,CPU还要进行很多准备工作:检测渲染状态、提交渲染所需要的数据、提交渲染所需要的状态。而GPU本身具有很强大的计算能力,可以很快就处理完渲染任务。当DrawCall过多,CPU就会很多额外开销用于准备工作,CPU本身负载,而这时GPU可能闲置了。
优化方法例如批处理(Batching):尽量把小的DrawCall合并到一个大的DrawCall中,这就是批处理的思想。使用批处理我们需要在CPU和RAM中合并网格,合并的条件至少是:同材质、同贴图、同shader,最好网格顶点格式也一致。
https://zhuanlan.zhihu.com/p/26077873?refer=c_83023344

10. 实例化?

实例化这项技术能够让我们使用一个渲染调用来绘制多个物体,来节省每次绘制物体时CPU -> GPU的通信,它只需要一次即可。如果想使用实例化渲染,我们只需要将glDrawArrays和glDrawElements的渲染调用分别改为glDrawArraysInstanced和glDrawElementsInstanced就可以了(注意实例化数组的使用)。
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/10%20Instancing/

11. 边缘检测算子:Sobel算子、Canny算子等。

https://www.cnblogs.com/wj-1314/p/9800272.html

  1. 提前深度测试:
  2. 现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性。提前深度测试允许深度测试在片段着色器之前运行。只要我们清楚一个片段永远不会是可见的(它在其他物体之后),我们就能提前丢弃这个片段。片段着色器通常开销都是很大的,所以我们应该尽可能避免运行它们。当使用提前深度测试时,片段着色器的一个限制是你不能写入片段的深度值。如果一个片段着色器对它的深度值进行了写入,提前深度测试是不可能的。OpenGL不能提前知道深度值。
    https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/01%20Depth%20testing/

12. 卡通着色(Toon Rendering/ Cel Rendering):卡通着色基本的三个要素

  • 锐利的阴影(Sharp shadows)
  • 少有或没有高亮的点(Little or no highlight)
  • 对物体轮廓进行描边(Outline around objects)

使用 2-tone 方法来表示光照效果和阴影区域。也称为硬着色方法(Hard Shading),可以通过将传统光照方程元素重新映射到不同的调色板上来实现。具体的着色方法,可以理解为在 Fragment shader 中测试每个像素漫反射 diffuse 中的 NdotL值,让漫反射形成一个阶梯函数,不同的 NdotL 区域对应不同的颜色。
参考《RTR3提炼总结》P166-P167

13. 描边算法:轮廓描边的渲染方法?

分为以下五种:

  • 基于视点方向的描边
  • 基于过程几何方法的描边
  • 基于图像处理的描边
  • 基于轮廓边缘检测的描边
  • 混和轮廓描边

参考《RTR3提炼总结》P167-P171
另外可参考:https://zhuanlan.zhihu.com/p/25939794
https://blog.csdn.net/candycat1992/article/details/45577749

14. 判断点是否在三角形内:

https://www.cnblogs.com/graphics/archive/2010/08/05/1793393.html

15.射线与球体相交检测?

联立光线方程和表面方程求解方程。

16. 如下图

在这里插入图片描述
就是空间管理的问题,直接采用BVH树判断即可。

17. 漫反射方程1/π的由来?

面试知识总结——图形学/OpenGL/3D数学/Unity_第3张图片

18. 怎么光栅化一个三角形?

计算三角形的最小包围盒,判断包围盒中的每个像素是否位于三角形内,是的话则进行着色。

19. PBR知道吗?它的一些模型?比如高光模型这些?

PBR即基于物理的渲染。渲染方程(Render Equation)是用来模拟光的视觉效果最好的模型。而PBR的渲染方程是用以抽象地描述PBR光照计算过程的特化版本的渲染方程,被称为反射方程。
面试知识总结——图形学/OpenGL/3D数学/Unity_第4张图片
fr 就是双向反射分布函数(Bidirectional Reflectance Distribution Function, BRDF),它的作用是基于表面材质属性来对入射辐射度进行缩放或者加权。Cook-Torrance BRDF分为漫反射和镜面反射两个部分。其中高光模型由3个函数(D,F,G)和一个标准化因子构成。

  • D (Normal Distribution Function,NDF):法线分布函数,估算在受到表面粗糙度的影响下,取向方向与中间向量一致的微平面的数量。这是用来估算微平面的主要函数。
  • F(Fresnel equation):菲涅尔方程,描述的是在不同的表面角下表面反射的光线所占的比率。
  • G(Geometry function):几何函数,描述了微平面自成阴影的属性。当一个平面相对比较粗糙的时候,平面表面上的微平面有可能挡住其他的微平面从而减少表面所反射的光线。

用来实现相应物理机制的每种函数都有不止一种形式。它们有的非常真实,有的则性能高效。Epic Games在Unreal Engine 4中所使用的函数:其中D使用Trowbridge-Reitz GGX,F使用Fresnel-Schlick近似法(Approximation),而G使用Smith’s Schlick-GGX

20. 知道什么是IBL吗?怎么生成cubemap?

基于图像的光照。反射方程中计算漫反射辐照度的部分可以预计算出一个新的cubemap,这个cubemap存储了用卷积(convolution)计算出的每个采样方向(或像素)ωo的漫反射积分结果。
卷积(convolution)是对数据集的每个入口应用一些计算,假设其它所有的入口都在这个数据集里。此处的数据集就是场景辐射或环境图。因此,对cubemap的每个采样方向,我们可以顾及在半球Ω的其它所有的采样方向。
为了卷积环境图,我们要解决每个输出ωo采样方向的积分,通过离散地采样大量的在半球Ω的方向ωi并取它们辐射的平均值。采样方向ωi 的半球是以点p为中心,以ωo为法平面的。
面试知识总结——图形学/OpenGL/3D数学/Unity_第5张图片
这个预计算为每个采样方向ωo存储了积分结果的cubemap,可被当成是预计算的在场景中所有的击中平行于ωo表面的非直接漫反射的光照之和。这种cubemap被称为辐照度图(Irradiance map)。

21. 深度测试在PC端和移动端的不同?在什么阶段做,光栅化前还是之后?

  • 第一个问题不懂,也查不到。
  • 深度测试是在片元着色器之后执行的,也就是光栅化之后。但现代GPU有提前深度测试技术,在光栅化之前。

22. SSAO的原理?

对于铺屏四边形上的每一个片段,我们都会根据周边深度值计算一个遮蔽因子。这个遮蔽因子之后会被用来减少或者抵消片段的环境光照分量。遮蔽因子是通过采集片段周围球型核心(Kernel)的多个深度样本,并和当前片段深度值对比而得到的。高于片段深度值样本的个数就是我们想要的遮蔽因子。

23. 头发怎么渲染?

参考知乎收藏,暂时未研究

24. 阴影的做法?

Shadow Mapping
参考阴影映射

25. 静态光照的烘培技术了解过吗?

参考《全局光照技术》第8章,辐射度方法。

26. 光线追踪为什么会出现噪点,怎么解决?

产生噪点主要有两个原因:

  • 积分过程中光线采样不足
  • 生成入射光线样本与真实光线的分布有偏差。

在光线追踪过程中,如果能精确的求解出渲染方程,算出每个点的反射颜色,那么渲染出的图片接近真实照片,不会出现噪点。在求解方程的过程中,对于每个点反射光线的颜色是自发光颜色+反射光颜色,对于自发光部分一般为一个常数值,而反射部分则是一个半球上的积分计算。对于理想镜面反射,光线的反射只在一个方向上有值,并不需要生成很多样本去做积分运算,可以做特殊处理,但是对于漫反射部分,如果要精确的计算出结果,则需在对入射到该点的半球面上的所有光线做积分运算,而直接求解该方程的积分比较困难,在实际光线追踪应用中则是使用蒙特卡罗的方式近似求解。而在积分过程中需要采样大量的光线样本才能让积分收敛接近真实值,如果采样不足或者生成的光线样本分布与真实光线的分布存在偏差就可能会出现噪点。

如何解决噪点问题呢?
噪点是因为采样引起的,因此我们可以改进采样来降低它,分为两种方法:

  • 其中改进采样最简单有效的解决办法是提高光线采样数量,对于路径追踪来说,就是提高每个像素点随机生成的光线路径数量。但是提高采样数量一方面会增加计算时间,另一方面采样数量与噪点收敛并不成线性比例,采样数量提高到一定程度后,噪点降低的幅度变化很小。
  • 另外一种改进采样的方法是重要性采样(Importance Sampling),由于均匀采样(Uniform Sampling)生成的光线样本在各个方向上概率都相同,并不会对灯光特殊对待。在实际应用中,如果能让随机生成的光线样本有极大的概率偏向灯光的方向也可以减少噪点。为了防止对灯光的过度采样,我们还需要对采样的结果用概率密度函数(pdf-probability density function​ )做权值调整。这种非均匀采样,再对采样结果用pdf加权调整的方式叫重要性采样。

除此之外,还有一种方法是对最终生成的图像做后期处理以实现降噪,即通过降噪算法,将极低采样的光线追踪结果重建出非常接近用大量采样渲染得到的收敛后的图像。

27. 静态阴影和动态阴影怎么混合?

???

28. 光线追踪的抗锯齿怎么解决的?

增大采样率

29. 怎么渲染镜子里面的物体?

使用模板缓冲
参考 https://blog.csdn.net/sck5711/article/details/4036316

30. 如何求正交矩阵的逆?

正交矩阵的转置矩阵和逆矩阵相等

31. 做纹理映射的时候为什么要做透视矫正?以及为什么要做?

当以透视投影渲染场景时,由于透视收缩的影响,在对顶点属性进行插值时必须进行透视校正,简单地说就是要把插值后的每个顶点属性值除以对应的z坐标,否则纹理会扭曲。(经过透视变换进入屏幕空间后,纹理坐标不再是线性变化的)
(https://blog.csdn.net/popy007/article/details/5570803
https://blog.csdn.net/nice_xp/article/details/89067461)

32. 对顶点的法线和位置进行变换的时候有没有区别?可不可以用同一个矩阵?什么时候可以用同一个矩阵?

一般情况下,对位置进行变换的矩阵M,若要同时进行法向量变换,需要用M的逆转置矩阵。然而,当M不包含非统一缩放或者切变的时候,可以直接用M进行法向量变换。

33. 欧拉角、四元数、矩阵描述旋转的优缺点?

34. 如何判定圆形和线段是否相交?(要求用线性代数的方法)

35.msaa发生在什么阶段?延迟渲染为什么对msaa支持不好?

光栅化阶段。主要原因是带宽消耗太大。参考延迟渲染与MSAA的那些事

36.检测点是否在扇形之内

面试题:检测点是否在扇形之内

你可能感兴趣的:(面试知识总结,图形学)