图形学渲染流程(管线)说一下
答: 传统的前向渲染管线流程是这样的 顶点和索引到顶点着色器,这里主要是对顶点进行变换,然后是光栅化,这里将剔除视锥体之外的元素,光栅化后三角形内的像素将进入到片元着色器(像素着色器),经过深度测试(模板测试)后写入到Target缓冲区内。 其实还有计算shader,用于曲面细分的三个shader,几何shader,RayTrace shader等,不展开了。
BDRF函数
答:BRDF函数是射出光线的辐照度和摄入光线辐射率的比值,在现代引擎中BRDF一般使用Cook-Torrance 的公式,定义为F菲涅尔(F0,NV) G(L,N,V) 几何函数 D(N,H,Roughness) 法线分布函数(H为L,V的半角向量) 除以4*(NL)*(NV)
IBL基本原理
答:
在PBR渲染公式中,我们不仅仅算直接光源,也要考虑来自环境的间接光源,因此把来自环境光的信息储存在cubeMap中供计算,这就是IBL,基于图形的光照,在这种情况下需要对光照方程进行分割,分为环境光和镜面光两部分,为了提高速度一般都会把这些卷积的结果存储在贴图里面,对于漫反射,存不同法线下的卷积结果,对于高光需要先分拆为 预滤波环境贴图和预计算BRDF,这里有一个N=V=R的假设,基于重要性采样,可以把第二项看为参数为NWi和Roughness参数的二维函数,就可以预计算贴图,从而实现快速运算。
全局光照算法
答:不好说。 光照探针进行混合?球谐函数?PBR? VXGI?
阴影贴图的原理和流程
答:阴影贴图是以光源为视点,通过深度缓冲获取一张深度贴图,然后在渲染过程中,将点通过矩阵转换到光源的投影空间,通过比较深度大小,确定是否处于阴影当中。阴影贴图可以使用32位来存储 。
透明物体渲染?交叉叠加怎么办?
先排序,后叠加,可以从后往前渲染,也可以从前往后渲染。
八叉树空间划分,场景里物体会动怎么办?
答:八叉树是四叉树在三维空间的变种,它将场景分为八个子空间,即每个节点有八个子节点,八叉树可以用于加速视锥体裁剪,加速射线检测,加速碰撞检测,加速范围内物体检测。
场景物体运动的话,可以先把物体从节点中移除并插入到新的节点当中,为了加速,可以先检测是否新的节点还位于父节点中,从而减少开销。
除了视锥体裁剪还有什么裁剪方式
答:视锥体裁剪 视口裁剪 可见性剔除 场景剔除 背面剔除 遮挡剔除
渲染管线详细流程
答:Vertex Shader -> 光栅化,裁剪->Pixel Shader->深度测试->Buffer
MVP矩阵的含义 为什么发现变换要乘model的逆矩阵的转置矩阵
答 :M->model 矩阵 点位于局部坐标,通过model矩阵变换到世界坐标
V->view矩阵 将点从原点变换到以视点为基点的坐标
P->projection矩阵 将三维坐标投影到二维坐标 NDC空间当中
Model变换会导致法线变换后不与面垂直,需要model逆变换转置。
什么是early-z 什么情况下会失效
在vertex shader和fragment shader之间做的一次深度测试 如果不通过的话就舍弃 通过的话还需要最后的ztest 失效情况 通过测试后依然有可能被别的vertext遮挡 需要在fragment完成后在屏幕空间在做一次ztest测试。
阴影反走样的depth-bias 和pcf原理
答:由于贴图分辨率的问题,会出现条纹现象,可以加一个偏移(比如0.05)来修正,
同时考虑到这样生成的阴影会过影,没有过渡,而实际的阴影一般是软阴影有着过渡,可以使用pcf方法,采样附近的深度值平均一下来确定阴影。
Phong(冯氏)和blinn-Phong光照模型
答:冯氏光照模型是第一个被广泛应用的光照模型,它把光分为环境光,漫反射光和高光,环境光为常量,漫反射光取决于入射光和法线的点积,高光取决于出射光和视线的夹角,但这样有一个坏处那就是视角有时会和入射光在同一方向,这时候高光就会抛弃,形成一个不平滑过渡,Blinn-Phong改进了这一点,把高光改成入射光线和视角的半角向量和法线的点积。
法线贴图TBN矩阵的推导过程,为什么要有切线空间
法线贴图的法线是相对于Z轴而言的,如果面的位置发生变换,那么法线就会不正确,因此把法线定义到TBN空间。
CSM和VSM的原理和流程
答:ShadowMap的改进,待补充。
SSAO基本原理 缺陷 优化
答:SSAO屏幕空间遮蔽首先通过深度测试生成一张深度贴图,然后在渲染中对于每个像素,在其切线空间确定的半圆空间内随机采样,将这些采样的pos变换到屏幕空间进行深度比较,最终确定AO值并生成一张AO贴图,参与最后的光照运算。
由于视点移动以及随机采样等因素,SSAO往往需要使用平滑滤波的方式来消除采样较少或不足所产生的噪点。
GPU动态分支是编译多份shader还是一个动态分支
答:没看懂,静态分支一份shader,动态分支为了 wrap的同步,也会展开执行?不懂。
采样shadowmap点光源要用cubemap 如何采样 cubemap的uv坐标代表什么
答:从六个角度进行采样,FOV设定为90° cubemap有三个坐标代表x,y,z向量。
shadowMap比较深度值时候 是在线性空间吗 需不需要除w
答:不是 不需要除w
发射射线用于屏幕空间物体的拾取的机制 如何加速射线和三角片元的检测速度
答: 将屏幕空间的x,y转换到ndc再转换到view空间,再转换到world空间,再转换到物体的model空间。首先和包围盒进行相交检测,再分别和里面的三角形进行检测。加速:可以使用LOD进行检测。
A*算法
答:最常见的路径搜索算法,维持一个open和closed表,每个节点维持一个G(起点到当前的代价) H(点到终点的代价) 每次从open表中选择F=G+H最小的点出队,如果该点等于终点则结束,否则将该点入close表,并搜索该点的邻居中不在close的邻居,并更新他们的G和H,重新插入到open表。
什么是MSAA 说一下原理
答:MSAA是常见的抗锯齿(反走样)技术,它的代价较低,效果也不错。它的原理是使用一个分辨率更大的深度缓冲区,并进行深度测试,在最后的输出阶段,根据每个像素对应的多个深度缓冲信息来进行着色,例如4xMSAA,一个像素对应了四个含深度信息的像素,如果最后只有两个深度像素通过了测试,那么它的颜色值应当乘0.5,但是MSAA借助的是深度缓冲,显然无法处理Alpha透明元素,并且时域表现上并不稳定,还有由于信息生产是在光栅化阶段,是几何层面上的反锯齿,对于次像素着色无能为力。
为什么通过GBuffer延迟渲染不能使用MSAA(腾讯面试问的)
答:MSAA相比于传统的深度缓冲,需要更大分辨率的深度缓冲来记录深度信息,而延迟渲染的第一个Pass内进行的深度测试就将未通过深度测试的像素舍弃掉,这意味着后面的Pass无法获得需要的足够的深度信息,除非增大GBuffer,带宽上有很难接受。
说一下常见的抗锯齿算法以及原理
答:MSAA 见上
SSAA 计算更大分辨率的像素值,最后把它们多合一,效果最好,成本最高。
FXAA 主要是基于屏幕空间的后处理技术。会对边缘进行模糊。
TAA 常用于延迟渲染。不同于SSAA在同一帧上的采样,TAA将采样分布到了
多个帧(8-16个),这样就可以利用前面帧的信息进行采样。具体原理是在每个帧上对采样的位置做一个次像素的偏移,然后和以前的结果进行累加。以前像素位置的计算是把当前的WorldPosition *WVP-1*WVPlast 如果是动态物体还要加上motion(可见还需要一个Velocity Map)。但这个技术的问题是如果像素帧间像素被遮挡等产生的 无效像素会产生鬼影。
渲染透明物体应该怎样控制状态机
答案:渲染透明物体应当使用单独的pass,对透明物体按Z轴进行排序,从后往前进行渲染。
说一下前向渲染和延迟渲染,各有什么优缺点(腾讯面试问的)
答:前向渲染是传统的渲染流程,对带宽的要求相对较小,但是由于深度测试是最后进行的,会导致很多无效的计算,同时对多光源的支持也不好。
延迟渲染有多个pass,第一个pass是将如深度信息,法线信息,材质信息,阴影AO信息写入到一个GBuffer中,一般GBuffer都会超过32位,则需要MRT技术(除非使用延迟光照),然后取渲染每个光源对应范围的几何体,渲染时候应关闭深度测试,使用着色方程渲染即可。
可以看到延迟渲染对带宽有较大的需求,这里有两种解决的方法,一种是将着色方程分离,将环境光和漫反射高光分离开来,多个Pass,最后合并起来。第二个便是手机上常用的分块着色,它基于这样一个问题,如果光源特别多的话,那么对于每个光源计算每个像素的光照的话会有比较大的开销,如果是反过来,对于每个像素,只计算受影响的光照就会好很多,但是每个像素储存光照列表并不现实,可以以块为单位,每个块记录光照表的一个索引和偏移,表示受哪些光照影响,则可以大大降低带宽占用。当然分块渲染也存在着易受无关光源影响的问题,对应的有分簇渲染。
光照存储方式 有很多种 2D 3D CubeMap SH(球谐)函数 解释一下这些方式的优缺点
答:
1.用球谐系数来存储间接光源可以避免用HDR或者数组等来存储间接光源造成的内存消耗。
2.由于使用的球谐阶数有限,高频部分的光源会丢失。
对于1能节省内存特别是像ue4 Volumetric Lightmaps有很多个间接光源采样点的时,优势更加明显,对于2,会使得光照变得更加的柔和,所以球谐光照不适合用来表示直接光照,比较适合来用来存储比较柔和的间接光源。
纹理采样时透视矫正的原因和方法
答:物体经透视变换后,UV坐标的变化是非线性的,但是采样的话依旧是线性的,所以会产生变形。因此UV坐标需要先除以Z,才能保证采样不变形。
D3D11格式,R8G8B8A8_UNORM与R16G16_UNIT的含义以及范围
答:四个通道,每个通道各占8位 范围[0,1]浮点
两个通道,每个通道各占16位,范围[0,INT_MAX] 整型
Texture Atlas的概念和作用
答:由于在多个纹理之间切换有代价,可以将多个纹理合并成一个纹理,这个技术称为Texture Atlas。 具体的资料不多,RTR4 讲的很简单,需要翻论文。
齐次坐标的作用是什么,为什么图形学需要齐次坐标。
答:齐次坐标是多加一维的向量,(x,y,z,w) 当w=0时表示的是向量,无法进行平移变换,如果w=1表示的是点,可以进行平移。
点积的物理含义是什么,叉积的物理含义是什么,叉积的模物理含义是什么
答: 这题目搞不懂什么叫物理含义,力的功?估计是几何含义的意思。点积,一个向量在另外一个向量投影的长度乘该向量的模的积。叉积,垂直于两向量的向量,模大小是两向量模的乘积乘sinθ
已知入射光线和法线,求反射光线,用线性代数的方法,写出伪代码
答: 线性代数不懂啥意思,弄个矩阵?
Assumed N,L Has Normalized R=-L+2N*(N ·L)
Code: R=reflect(L,N) Float3 R=-L+2xNxdot(N,L)
怎样判断光线和三角形相交
答: 直观做法:先判断光线是否和三角形所在平面相交,在判断交点是否在三角形内部,第一个步骤联立方程即可,第二个的话看交点和三角形三个点夹角和是否为180度。但这个方法效率极低。
使用的方法是射线方程 V=V0+ut 和UV代表的三角形点V=E1U+E2V 联立,求t,u,v 利用克拉默法则即可求交点信息。
什么情况下可以避免使用TBN(法线)矩阵
答:在片元着色器中构建TBN矩阵代价较大,可以反过来将光源变换到TBN矩阵空间,具体方法是乘TBN逆矩阵,这样可以避免直接使用TBN矩阵。
透明混合中一般都是从后往前混合,如何反向进行Alpha混合
答:从后往前渲染:co = Scs +(1-s) cd (s source d destination)
从前往后渲染 :
知道2d坐标 深度值 以及Projection矩阵 如何求出原来的3d坐标
答:由2d坐标x,y和深度z,构建(x,y,z,1)向量,再乘以Projection矩阵的逆矩阵,
最后除w。
GPU的NDC坐标是什么
答:设备坐标标准化是在透视变换后,坐标可能位于[-r,r]之间,将其归一化为[-1,1]
分别写出缩放矩阵,平移矩阵,绕X轴旋转矩阵
答:缩放
平移
坐标轴转
说一下四元数
答:四元数通常用来表示旋转,通常表示为 其中a为旋转轴,θ为旋转角。四元数可以做插值来表示渲染的插值,也可以做乘法QaQb表示先沿着a旋转,再沿着b旋转。 表示四元数的共轭和逆。
四元数旋转矢量的公式是:
四元数插值表示:
四元数的球形插值表示:
说一下次表面反射 一般用于什么材质
答:次表面散射主要是由于光线进入透明或半透明物体后经多次折射后从另外一个点射出而产生的效果,一般用于模拟皮肤,玉石,蜡烛等。
说一下反射算法 SSR
答:屏幕空间反射算法,一种常见的实现反射效果的方法。原理是对于每个像素,求出视角射线在平面上反射射线,并按照步进进行采样,将采样点转换为屏幕空间坐标,并和屏幕上的像素做深度比较,一旦小于某个阈值,即可停止采样。
缺点是只能采样屏幕空间的像素,屏幕外的就无能为力了。资源消耗大,粗糙物体处理不好。
说一下贴图采样的双线性插值 三线性插值 各向异性
答:双线性插值使用四个像素进行插值,取平均值。三线性插值在双线形插值的基础上再使用不同级别的MipMap进行插值。 各向异性插值会根据透视的形变程度在不同的方向上取一定的像素进行重采样。具体的实现方式没咋看,资料也很少。
如何基于SIMD实现4x4矩阵的转置
答:
#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) { \
__m128 _Tmp3, _Tmp2, _Tmp1, _Tmp0; \
\
_Tmp0 = _mm_shuffle_ps((row0), (row1), 0x44); \
_Tmp2 = _mm_shuffle_ps((row0), (row1), 0xEE); \
_Tmp1 = _mm_shuffle_ps((row2), (row3), 0x44); \
_Tmp3 = _mm_shuffle_ps((row2), (row3), 0xEE); \
\
(row0) = _mm_shuffle_ps(_Tmp0, _Tmp1, 0x88); \
(row1) = _mm_shuffle_ps(_Tmp0, _Tmp1, 0xDD); \
(row2) = _mm_shuffle_ps(_Tmp2, _Tmp3, 0x88); \
(row3) = _mm_shuffle_ps(_Tmp2, _Tmp3, 0xDD); \
}
思想:分块(2x2) 转置 矩阵乘法的simd也是要看的
判断一个点在任意多边形之间的算法
答: 自己以前用的一个方法,取点朝任意方向发射一条射线 ,求出该射线和多边形之间交点的个数,若是奇数在内,偶数在外。
合适的方法:射线方程R=P+ut 和三角形上点左边方程 P=uE1+vE2 联立即可。
透视矩阵的推导
答:屏幕空间的NDC坐标(x1,y1) ( -1<=x<=1 -1<=y<=1 ) 和原来视角空间的坐标(x,y)关系为:
x'=xrztanα2 y'=yrztanα2
透视矩阵不会除以Z ,变换后的(x,y,z,w) W=Z,会通过除以W实现除以Z,要保证新的Z的范围位于[0,1] ,所以透视矩阵为:
辐射通量 辐照度 辐射强度 辐射率(辐射亮度) 分别是什么
正交阵如何快速求逆?
答:转置即可
绕任意轴旋转怎么推导
答:见龙书,麻烦但理解不难。
什么是伽马矫正,有什么用?
答:显示器CRT的伽马曲线是非线性的,因此线性空间的颜色在显示的时候会失真,事实上是2.2幂次方的曲线,因此最后的颜色值要除以2.2幂次方。但是一般来说贴图都是经过伽马矫正的,因此要先做2.2幂次方运算。
说一下常见的SIMD指令 比如_mm_shuffle_ps ,mm_dp_ps 它们的掩码是怎么用的
答:_mm_shuffle_ps可以从两个 __m128向量中任意提取四个Float,掩码是八位,从低位到高位,分为4个部分,每个部分两位,指定四个Float中的某个Float。在矩阵转置,矩阵乘法中用得到。
_mm_dp_ps 可以做两个 __128 向量的点积。
来源:CSDN
作者:Alevery
链接:https://blog.csdn.net/qq_36263056/article/details/104464522